Using two (or more) objects as a HashMap key

2019-01-22 04:04发布

I want to store certain objects in a HashMap. The problem is, usually you just use a single object as a key. (You can, for example, use a String.) What I want to do it to use multiple object. For example, a Class and a String. Is there a simple and clean way to implement that?

标签: java hash map
8条回答
成全新的幸福
2楼-- · 2019-01-22 04:36

You could create a holder class that contains the class and string that you want as the keys.

public class Key {

    public MyClass key_class;
    public String key_string;

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

}

Probably not the best solution, but a possibility.

查看更多
乱世女痞
3楼-- · 2019-01-22 04:37

Apache Commons Collections has a multikey map which might do the trick for you:

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

It looks like it will handle up to 5 "keys".

查看更多
混吃等死
4楼-- · 2019-01-22 04:41

One can solve this issue using apache's commons collection lib's MultiKey class. Here is a simple example:

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)); 
查看更多
趁早两清
5楼-- · 2019-01-22 04:43

There are a few places where people suggest creating a "Key" class containing the others, I totally agree. Just thought I'd add a helpful hint.

If you use eclipse or netbeans, they have a nice option--you can tell Eclipse to create equals and hashcode methods based on one or more members. So you just select the member (or members) you want to retrieve by and NB creates most of the code you'd need to write for you.

of course when I just want to retrieve by one object, I often just delegate the hashcode and equals methods to that object (delegating equals might be problematic because it would mean that one of your "Key holder" classes would be equal to the object that is it's key, but that's pretty easily fixed (and wouldn't usually effect anything anyway)

so off the top of my head:

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();
    }
}

That's all there is to it, and eclipse will do the last two for you if you ask it to.

By the way, I know that I have public members, a public final member is exactly the same thing as having a getter--not really a terrible idea. I'm starting to use this pattern on small utility classes like this a lot more lately. If the member wasn't final, it would be worse because it would be like having a setter (Something I try to avoid these days).

查看更多
倾城 Initia
6楼-- · 2019-01-22 04:44

You key must implement the hashCode and equals. If it is a SortedMap, it must also implements the Comparable interface

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");
查看更多
来,给爷笑一个
7楼-- · 2019-01-22 04:49

The easiest way that I know of is to make a wrapper class and override hashmap and equals. For instance:

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();
    }
}

OF course, I would recommend using a StringBuilder and whatever else, but this way you have overridden the equals and hashcode, thereby allowing a hash and equality check on your multiple keys.

Also, I would recommend making the objects immutable (not editable) for safety's sake, but that is purely preference.

查看更多
登录 后发表回答