java中的嵌套映射或组合键

java中的嵌套映射或组合键,java,key,hashmap,Java,Key,Hashmap,我需要一个映射来在Java中为我有两个字符串键的相同值创建缓存。我的问题是,最好是制作嵌套映射(每个键对应一个映射)或使用两个字符串制作某种类型的自定义键 对缓存上数据的访问将始终使用两个键进行访问,我不需要按这两个键中的任何一个对其进行分组 那么,如果最好只在一个字符串中组合字符串键,那更好吗 使用自定义getHash方法的自定义类。但问题是哈希函数实现了什么 只需将两个字符串连接在一起。例如: cache.put(key1+key2,value) 对我来说,使用组合键更符合逻辑,也更易于使

我需要一个映射来在Java中为我有两个字符串键的相同值创建缓存。我的问题是,最好是制作嵌套映射(每个键对应一个映射)或使用两个字符串制作某种类型的自定义键

对缓存上数据的访问将始终使用两个键进行访问,我不需要按这两个键中的任何一个对其进行分组

那么,如果最好只在一个字符串中组合字符串键,那更好吗

  • 使用自定义
    getHash
    方法的自定义类。但问题是哈希函数实现了什么
  • 只需将两个字符串连接在一起。例如:

    cache.put(key1+key2,value)


对我来说,使用组合键更符合逻辑,也更易于使用(您不必担心嵌套映射被实例化)

关于键的组合,请使用自定义类。它在语义上更有意义,如果您有相似的字符串,它可以防止出现冒号。如果您有键
[“ab”,“c”]
和键
[“a”,“bc”]
,则可能出现这种冲突

请记住,在编写自定义类时,需要正确编写
equals
hashCode
方法,否则缓存可能无法工作(并且可能会出现性能问题)

最好制作嵌套映射(每个键对应一个)或使用两个字符串制作某种类型的自定义键

具有复合键类型的单个哈希表可能具有更好的引用局部性。它几乎肯定会占用更少的内存,而且速度会快一点,不过具体速度取决于您的应用程序


设计自定义散列函数可能很棘手,但您可以从一个函数开始,该函数只接受已定义的复合键成员散列并将它们异或在一起。您也可以采用字符串路由,但要确保在成员之间连接一些不太可能出现的标记(如“:”)。

您可以创建嵌套映射,也可以使用自定义类定义
hashCode()

连接键通常不是一个好主意,可能会导致冲突,例如键
1
22
以及键
12
2
。它们将映射到相同的值
122

如果您总是使用两个键,那么使用单个
Map
将总是更有效一些,并且您可以始终为Map定义自己的适配器,该适配器将包含两个参数:

public class MyCache { 

    private Map<MyKey, Object> cache = new HashMap<MyKey, Object>();

    public Object getObject(Object key1, Object key2){
        return cache.get(new MyKey(key1, key2));
    }
    public void putObject(Object key1, Object key2, Object value){
        cache.put(new MyKey(key1, key2), value);
    }
}

我认为使用嵌套贴图不是最好的方法。 我同意您的第二个想法-使用重写的
hashCode

实现自定义类

public int hashCode(){
   return str1+str2.hashCode();
}
public boolean equals(Object o){
   //compare both keys here
}

等于

public int hashCode(){
   return str1+str2.hashCode();
}
public boolean equals(Object o){
   //compare both keys here
}
另外,不要忘记重写存储对象类中的相同方法


那么,在[ab(c)]的情况下,你将得到相同的哈希代码,但是不同的结果等于

你可能想考虑番石榴的类。它们实现了一个
映射
,每个值有两个键。根据您的需求,这可能会提供比组合键更可读的解决方案

Table<String, String, MyValue>
表格

我在缓存系统中遇到了类似的问题,该系统需要使用方法参数生成密钥。我最终编写了一个类似于Xavi答案的包装器类

public final class ArrayWrapper 
{
    private final Object[] array;

    public ArrayWrapper(final Object... array)
    {
        this.array = array;
    }

    public Object[] getArray()
    {
        return this.array;
    }

    public boolean equals(Object o)
    {
        if (o == null) return false;
        if (o == this) return true;
        if (o instanceof ArrayWrapper)
        {
            return Arrays.equals(this.array, ((ArrayWrapper)o).array);
        }
        return false;
    }

    private int hashCode(Object o)
    {
        if (o == null) return 0;
        return o.hashCode();
    }

    public int hashCode()
    {
        int sum = 17;
        if (this.array != null) for(int i = 0;i<this.array.length;i++)
        {
            sum = 37 * sum + this.hashCode(this.array[i]);
        }
        return sum;
    }

    public String toString()
    {
        if (this.array != null)
        {
            return "Wrapper " + Arrays.toString(array);
        }
        else return "Wrapper []";
    }
}
公共最终类数组说唱程序
{
私有最终对象[]数组;
公共ArrayRapper(最终对象…数组)
{
this.array=数组;
}
公共对象[]getArray()
{
返回此.array;
}
公共布尔等于(对象o)
{
如果(o==null)返回false;
如果(o==this)返回true;
if(阵列振打器的o实例)
{
返回array.equals(this.array,((ArrayWrapper)o.array);
}
返回false;
}
私有int哈希代码(对象o)
{
如果(o==null)返回0;
返回o.hashCode();
}
公共int hashCode()
{
整数和=17;

如果(this.array!=null)for(int i=0;它的数量如此之多,这正是我要寻找的!只是偶然发现了番石榴的多重映射,这对我来说不够方便。;)关于番石榴HashBasedTable的一个注释,它使用了嵌套映射方法。