使用两个(或更多)对象作为HashMap键

时间:2009-07-27 19:16:02

标签: java hash map

我想将某些对象存储在HashMap中。问题是,通常你只使用一个对象作为密钥。 (例如,您可以使用String。)我想要使用多个对象。例如,Class和String。是否有一种简单而干净的方法来实现它?

8 个答案:

答案 0 :(得分:14)

你的密钥必须实现hashCode和equals。如果它是 SortedMap ,它还必须实现Comparable接口

public class MyKey implements Comparable<MyKey>
{
private Integer i;
private String s;
public MyKey(Integer i,String s)
{
this.i=i;
this.s=s;
}

public Integer getI() { return i;}
public String getS() { return s;}

@Override
public int hashcode()
{
return i.hashcode()+31*s.hashcode();
}

@Override
public boolean equals(Object o)
{
if(o==this) return true;
if(o==null || !(o instanceof MyKey)) return false;
MyKey cp= MyKey.class.cast(o);
return i.equals(cp.i) && s.equals(cp.s);
    }

   public int compareTo(MyKey cp)
     {
     if(cp==this) return 0;
     int i= i.compareTo(cp.i);
     if(i!=0) return i;
     return s.compareTo(cp.s);
     }


 @Override
    public String toString()
       {
       return "("+i+";"+s+")";
       }

    }

public Map<MyKey,String> map= new HashMap<MyKey,String>();
map.put(new MyKey(1,"Hello"),"world");

答案 1 :(得分:10)

我倾向于使用列表

map.put(Arrays.asList(keyClass, keyString), value)

答案 2 :(得分:4)

我所知道的最简单的方法是创建一个包装类并重写hashmap和equals。例如:

public class KeyClass {

    private String element1;
    private String element2;

    //boilerplate code here

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof KeyClass) {
            return element1.equals(((KeyClass)obj).element1) &&
                element2.equals(((KeyClass)obj).element2);
        }
        return false;
    }

    @Override
    public int hashCode() {
        return (element1 + element2).hashcode();
    }
}

当然,我建议使用StringBuilder和其他任何东西,但这样你就重写了equals和hashcode,从而允许对你的多个键进行哈希和相等检查。

另外,为了安全起见,我建议让对象不可变(不可编辑),但这纯属首选。

答案 3 :(得分:3)

Apache Commons Collections有一个多键映射,可以帮到你:

https://commons.apache.org/proper/commons-collections/apidocs/org/apache/commons/collections4/keyvalue/MultiKey.html

看起来它最多可以处理5个“键”。

答案 4 :(得分:2)

你的意思是对象将被两个键键入,或者更确切地说是一个由两个键组成的键。

如果你想要第一个案例。也就是说,一个被两个键(比如一个类或一个对象)键入的对象,你需要使用两个地图。

Map<Key1, value>

Map<Key2, value>

在第二种情况下,您需要一张地图地图,所以:

Map<Key1, Map<Key2, value>>

答案 5 :(得分:1)

您可以创建一个包含所需类和字符串的holder类。

public class Key {

    public MyClass key_class;
    public String key_string;

    public Key(){
        key_class = new MyClass();
        key_string = "";
    }

}

可能不是最佳解决方案,但可能性。

答案 6 :(得分:0)

有些地方人们建议创建一个包含其他人的“Key”课程,我完全同意。我想我会添加一些有用的提示。

如果你使用eclipse或netbeans,他们有一个很好的选择 - 你可以告诉Eclipse基于一个或多个成员创建equals和hashcode方法。因此,您只需选择要检索的成员(或成员),NB就会创建您需要为其编写的大部分代码。

当然,当我只想通过一个对象检索时,我经常只是将hashcode和equals方法委托给该对象(委托equals可能会有问题,因为这意味着你的一个“Key holder”类将等于对象是它的关键,但这很容易修复(并且通常不会影响任何东西)

所以我不知道如何:

class KeyHolder {
    public final String key;
    public final Object storeMe;

    public KeyHolder(String key, Object storeMe) {
        this.key=key;
        this.storeMe=storeMe;
    }

    public equals(Object o) {
        return (o instanceof KeyHolder && ((KeyHolder)o).key.equals(key));
    }

    public hashcode() {
        return key.hashCode();
    }
}

这就是它的全部内容,如果你提出要求,eclipse会为你做最后两个。

顺便说一句,我知道我有公共成员,公共最终成员与吸气者完全一样 - 不是一个非常可怕的想法。我最近开始在这样的小实用程序类上使用这种模式。如果该成员不是最终成员,那就更糟了,因为它就像拥有一个二传手(我试图避免这些日子)​​。

答案 7 :(得分:0)

可以使用apache的commons集合lib MultiKey class来解决这个问题。 这是一个简单的例子:

import org.apache.commons.collections.keyvalue.MultiKey;

HashMap map = new HashMap();
MultiKey multiKey = new MultiKey(key1, key2);

map.put(multikey,value);

//to get 
map.get(new MultiKey(key1,key2));