代码之家  ›  专栏  ›  技术社区  ›  Gambler

使用两个(或更多)对象作为哈希映射键

  •  12
  • Gambler  · 技术社区  · 16 年前

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

    8 回复  |  直到 9 年前
        1
  •  14
  •   Pierre    16 年前

    键必须实现hashcode和equals。如果是 分类地图 ,它还必须实现可比较的接口

    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");
    
        2
  •  10
  •   ILMTitan    16 年前

    我倾向于用清单

    map.put(Arrays.asList(keyClass, keyString), value)
    
        3
  •  4
  •   kostmo    13 年前

    我知道的最简单的方法是创建一个包装类并重写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,从而允许对多个键进行哈希和相等性检查。

    另外,为了安全起见,我建议将对象设置为不可变(不可编辑),但这纯粹是首选项。

        4
  •  3
  •   mattm    9 年前

    ApacheCommons集合有一个多键映射,它可能会为您提供一些技巧:

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

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

        5
  •  2
  •   Sean Bright Sean Stinehour    16 年前

    你的意思是物体将由两个键,或者更确切地说,一个键由两个东西组成。

    如果你想要第一个病例。也就是说,一个对象有两个键,比如一个类或一个对象,你需要使用两个映射。

    Map<Key1, value>
    
    Map<Key2, value>
    

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

    Map<Key1, Map<Key2, value>>
    
        6
  •  1
  •   Berek Bryan    16 年前

    您可以创建一个holder类,该类包含您想要作为键的类和字符串。

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

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

        7
  •  0
  •   Bill K    16 年前

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

    如果您使用Eclipse或NetBeans,它们有一个很好的选择——您可以告诉Eclipse基于一个或多个成员创建Equals和HashCode方法。因此,您只需选择要检索的成员,nb就可以创建大部分需要为您编写的代码。

    当然,当我只想通过一个对象检索时,我通常只将哈希代码和equal s方法委托给该对象(委托equal s可能有问题,因为这意味着您的“key holder”类中的一个类将等于它的key对象,但这很容易修复(而且通常不会影响任何东西)。

    所以在我的头顶上:

    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将为你做最后两个。

    顺便说一句,我知道我有公共成员,一个公共的最终成员和一个有能手的人是完全一样的——不是一个很糟糕的主意。最近,我开始在类似这样的小实用程序类上使用这种模式。如果成员不是最后一名,那就更糟了,因为这就像拥有一名二传手(这是我最近努力避免的事情)。

        8
  •  0
  •   T.J. Crowder    14 年前

    可以使用apache的commons collection 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));