1

看起来 int[] 的 hashCode() 和 equals() 实现得很差,或者根本没有实现!(用 Android 测试过,但我希望它适用于任何 Java 环境)。

为了让 HashSet.contains() 正常工作,我不得不为 int[] 创建一个包装器(请不要批评我的编码风格,看本质):

public class IntArray {
    private int[] value;

    public IntArray(int[] value) {
        this.value = value;
    }

    @Override
    public int hashCode() {
        int sum = 0;
        // Integer overflows are cheerfully welcome.
        for (int elem: value) sum += elem;
        return sum;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null) return (value==null);

        if (value != null) {
            if (o instanceof int[]) 
                return compare((int[])o);

            if (o instanceof IntArray)
                return compare(((IntArray)o).value);
        }

        return false;
    }

    protected boolean compare(int[] other) {
        int len = value.length;
        if (other.length != len) return false;
        for (int i=0; i<len ; i++)
            if (value[i] != other[i]) return false;
        return true;
    }
}

工作正常,但我更喜欢避免使用自定义包装器或第三方库。有选择吗?

4

2 回答 2

1

由于标准 Java Hashtable 不允许覆盖用于键的哈希码,因此您很不走运,需要像您一样使用包装器。

请记住,您的 hashCode 实现非常糟糕,您可以使用它(取自标准 JDK 中的 java.util.Arrays)来获得更好的哈希分布:

public static int hashCode(int a[]) {
  if (a == null)
    return 0;

  int result = 1;
  for (int element : a)
    result = 31 * result + element;
  return result;
}

另一种方法是使用不同的 Hashtable,它可以处理原语。一个这样的选择是Banana,这是我创建的一个原始集合库。

于 2013-10-13T02:58:31.120 回答
0

在 Omry Yadan 的消息之后,hashCode 函数变得如此简单!

    @Override
    public int hashCode() {
        return Arrays.hashCode(value);
    }

对于 RISC CPU,比如 ARM,它可能更高效:

    @Override
    public int hashCode() {
        int code = 0;
        if (value != null) {
            code++;
            for (int elem: value)
                code = (code<<5) - code + elem;
        }
        return code;
    }

可能还有一个比较数组的标准函数,在这种情况下 equals() 也可以简化?

于 2013-10-13T05:00:14.117 回答