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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1190049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 00:41:01  来源:igfitidea点击:

Using two (or more) objects as a HashMap key

javahashmap

提问by Gambler

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?

我想在 HashMap 中存储某些对象。问题是,通常您只使用单个对象作为键。(例如,您可以使用字符串。)我想使用多个对象来做些什么。例如,一个类和一个字符串。有没有一种简单而干净的方法来实现它?

采纳答案by Pierre

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

您的密钥必须实现 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");

回答by ILMTitan

I tend to use a list

我倾向于使用列表

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

回答by Berek Bryan

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.

可能不是最好的解决方案,而是一种可能性。

回答by aperkins

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

我所知道的最简单的方法是创建一个包装类并覆盖 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();
    }
}

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.

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

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

另外,为了安全起见,我建议使对象不可变(不可编辑),但这纯粹是偏好。

回答by Ethan Heilman

Do you mean that the object will be keyed by two keys, or rather a key which consists of two things.

您的意思是该对象将由两个键键控,或者更确切地说是一个由两件事组成的键。

If you want the first case. That is, an objected keyed by two keys, say a class or an object, you need to use two maps.

如果你想要第一种情况。也就是说,一个由两个键组成的对象,比如说一个类或一个对象,你需要使用两个映射。

Map<Key1, value>

Map<Key2, value>

In the second case you need a map of maps, so:

在第二种情况下,您需要地图地图,因此:

Map<Key1, Map<Key2, value>>

回答by Clay Mitchell

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

Apache Commons Collections 有一个多键映射,它可以为您解决问题:

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

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".

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

回答by Bill K

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.

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

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.

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

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)

当然,当我只想通过一个对象检索时,我通常只是将 hashcode 和 equals 方法委托给该对象(委托 equals 可能有问题,因为这意味着您的“密钥持有者”类之一将等于该对象是关键吗,但这很容易解决(而且通常不会影响任何事情)

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.

这就是它的全部内容,如果您要求,eclipse 将为您完成最后两个。

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).

顺便说一句,我知道我有公共成员,公共最终成员与拥有一个 getter 完全一样——这并不是一个糟糕的主意。我最近开始在像这样的小型实用程序类上使用这种模式。如果成员不是最终成员,情况会更糟,因为这就像拥有一个二传手(这些天我试图避免的事情)。

回答by Asraful Forhad Chowdhury

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

可以使用 apache 的 commons collection lib's MultiKeyclass解决这个问题。这是一个简单的例子:

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