一组数字和一个特殊数字的好哈希?

时间:2016-11-03 20:00:53

标签: java algorithm math hash

我有整数数组,例如

[1, 3, 5], 
[7, 2, 10],
[50, 12, 10],
[20, 1, 34],

我试图制作一个散列算法,给定其中一个数组会为每个数组返回一个唯一的散列,以便我可以快速查看它们是否存在于HashMap中。

如果两个数组包含相同的数字集并且数组中的最后一个数字相同,则散列应该相同。

例如

// these are the same because they contain the same numbers and have same last number (5)
Hash([3, 1, 5]) -> 5678326 
Hash([1, 3, 5]) -> 5678326

// different hash because the last number in the array is different
Hash([5, 1, 3]) -> 9877124

// different hash because different set of values
Hash([7, 1, 5]) -> 2123466

数组中的值在0到100之间,并且它们都是唯一的(因此数组中没有重复项),并且数组的最大大小为100。

这对于什么是一个非常好的哈希算法?

4 个答案:

答案 0 :(得分:2)

计算输入的哈希码,就好像它是一个集合,乘以素数,并添加最后一个元素的哈希码。

沿着

的路线
new HashSet<Integer>(Arrays.asList(input)).hashCode() * 31 + input[input.length - 1]

但是对于性能,您可能希望通过循环添加输入项而不是创建HashSet来手动执行此操作。

请注意,这不会&#34;根据您的要求为每个[输入]&#34; 返回一个唯一的哈希值 - 您需要perfect hash function对于那些可能非常矫枉过正的事情。

答案 1 :(得分:1)

您所描述的是一种奇怪的设置,但实现它的一种方法是使用自定义对象:

public class YourCustomObject {
    private final int[] allButLast;
    private final int last;

    public YourCustomObject(int[] value){
        this.value = value;
        this.allButLast = Arrays.copyOfRange(value, 0, value.length-1);
        Arrays.sort(allButLast);
        this.last = value[value.length-1];
    }
    private final int[] value;

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }else if (( o instanceof YourCustomObject)) {
            YourCustomObject that = (YourCustomObject) o;
            return last == that.last && Arrays.equals(allButLast, that.allButLast);
        } else {
            return false;
        }
    }

    @Override
    public int hashCode() {
        return Objects.hash(allButLast, last);
    }

    public int[] getValue() {
        return value;
    }
}

此对象的equals / hashCode属性以任何顺序依赖于相同的数组元素,不包括最后一个元素,它必须相同。您可以将此对象用作HashMap中的键,它将按指定的方式工作。

此外,由于数组是可变的,我可能会在构造函数和getter中制作防御副本。

答案 2 :(得分:0)

不是最优化的解决方案,但它应该做你想做的事情:

int hash(int[] array) {
    array = array.clone();
    Arrays.sort(array, 0, array.length - 1);
    return Arrays.hashCode(array);
}

另一个选择是向集合中添加元素并调用Objects.hash(set, array[array.length - 1])

答案 3 :(得分:-2)

如果您只是为了将数组存储在Map或Set的存储区中而需要生成哈希值,则不需要创建自己的哈希函数。 java.util.Arrays中的那个会做。它们是专门为此目的而设计的。

此外,哈希码不必保证唯一 - 只是不太可能产生冲突。事实上,保证它们的独特性会比偶尔碰撞的速度慢得多。

无需重新发明轮子 - 只需使用java,util.Arrays.hashCode来计算数组的哈希码。