如何从3个整数组成HashMap的键?

时间:2015-04-10 16:48:23

标签: java hashmap

我需要从3个整数到对象的唯一映射。我不能对这些整数的值做任何假设,除了它们是积极的。

我目前使用这样的hashmap实现它:

int a = 10;
int b = 20;
int c = 30;
Map<String, MyObject> map = new HashMap<>();
map.put(a + "_" + b + "_" + c, myObject);

虽然这有效,但看起来有点难看。

有没有更好的选择,没有引入冲突,没有使用第三方库?

编辑:我刚刚意识到我实际上可以对我的整数做出更具体的假设。它们的重量都在1,000,000到2,000,000之间,它们的重量在底部,因为它们的序列开始计数为1,000,000。

4 个答案:

答案 0 :(得分:3)

final class Key{
     int a , b , c;
     public Key(int a , int b , int c){
         this.a = a;
         this.b = b;
         this.c = c;
     }

     public int hashCode(){
          return (a << 10 ^ b << 5 ^ c);
     }

     public boolean equals(Object o){
          if(!(o instanceof Key))
               return false;

          Key k = (Key) o;

          return (k.a == a && k.b == b && k.c == c);
     }
}

这甚至可以用于负值。

答案 1 :(得分:3)

你可以像这样创建一个Key类:

final class Key {
    final int a;
    final int b;
    final int c;

    Key(int a, int b, int c) {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Key)) {
            return false;
        }
        Key that = (Key) obj;
        return (this.a == that.a)
               && (this.b == that.b)
               && (this.c == that.c);
    }

    @Override
    public int hashCode() {
        return Objects.hash(this.a, this.b, this.c);
    }

}

将地图设为Map<Key, MyObject>

使用String的优点之一是类型安全。你无法做到这一点,例如:

map.put("Some arbitrary string that has nothing to do with numbers", myObject);

答案 2 :(得分:1)

因为每个值的范围最多有2M个不同的连续值,低于2 21 值,并且有3个这样的值,所以不同组合的数量低于2 63 。这些组合巧妙地(恰好)适合long值的范围(2 64 ),因此使用正确的数学,a,b和c的每个唯一组合都可以有自己的{{ 1}}值。

这是一个简洁且高性能的工具,它使用位操作来完成工作:

long

如果您制作地图的密钥类型// safe for a, b and c in range 0-2,097,151 (21 bits) private static long key(long a, long b, long c) { return a << 42 | b << 21 | c; } ,则可以使用此方法的结果作为密钥:

Long

我还没有测量Map<Long, MyObject> map = new HashMap<>(); map.put(key(a, b, c), myObject); 方法的性能,但它只有几个CPU周期。

答案 3 :(得分:0)

像某些答案所指出的那样,拥有自己的密钥类会起作用。像往常一样,使用哈希码和等号检测冲突。

就个人而言,我喜欢无限数量的整体选项,以提高灵活性。

public final class IntArrayKey{
    private final List<Integer> values = new ArrayList<>();
    private final int hash;
    private final String stringValue;

    public IntArrayKey(Integer ...ints){
        values.addAll(Arrays.asList(ints));
        hash = Arrays.hashCode(ints);
        stringValue = values.toString();
    }

    @Override
    public boolean equals(Object o){
        if(o == this) return true;
        if(!(o instanceof IntArrayKey)) return false;
        return values.equals(((IntArrayKey) o).values);
    }

    @Override
    public int hashCode(){
        return hash;
    }

    @Override
    public String toString(){
        return stringValue;
    }
}