累积字符串集合散列

时间:2011-05-02 21:07:31

标签: java collections performance hash

是否有可用于Java的算法,这将允许我继续添加String对象并删除旧对象,这样如果我添加了String然后将其删除,整数哈希将是相同的?

编辑:哈希中的字符串是唯一的。

一些伪代码:

h = hash
add(h, "hi!") == 51;
add(h, "hello again!") == 532;
rem(h, "hello again!") == 51;

我知道你可以使用Java集合来实现它,但默认实现必须继续遍历整个集合以收集哈希码。这对于大型集合来说效率非常低。我不介意使用外部库(如果存在)。

提前致谢,
克里斯

1 个答案:

答案 0 :(得分:2)

如果你不关心哈希算法是否具有加密质量(加密哈希算法很难正确指定;你搞砸了,有人可能会在你不希望它们时引起冲突),下面应该工作:

请考虑以下代码:

interface Accumulator<T, U>
{
    public void add(T t);
    public void subtract(T t);
    public U get();
}

class SumHasher implements Accumulator<String,Integer>
{
    @Override private int accumulator = 0;
    @Override public void add(String t) { accumulator += t.hashCode(); }
    @Override public void subtract(String t) { accumulator -= t.hashCode(); }
    @Override public Integer get() { return accumulator; }
}

class XorHasher implements Accumulator<String,Integer>
{
    @Override private int accumulator = 0;
    @Override public void add(String t) { accumulator ^= t.hashCode(); }
    @Override public void subtract(String t) { accumulator ^= t.hashCode(); }
    @Override public Integer get() { return accumulator; }
}

这些共同点是加法和XOR都是关联并且反转的操作。您可以按任意顺序执行它们并按任意顺序撤消它们,这样,如果add()中的每个元素Set<T>,则subtract()中的每个元素都会(x << k) | (x >>> (32-k))(不一定是相同的顺序),保证你得到0。

肯定有其他操作可以满足这个属性,但我不确定它们是什么。 (乘法不起作用,除非你能保证所累积的项目都没有值为0.这个答案过去常用f(x,h)=((x ^ h)+ h)^ h和g(x,h )=((x ^ h) - h)^ h作为反转,但这些函数不是关联的:以不同的顺序累积元素会产生不同的结果。

编辑 想到另一个简单的:基于输入值的按位置换(其中按位旋转是一种特殊情况)。在Java中,您可以使用x实现按位旋转,其中>>>是一个整数,k是0到31之间的整数(例如,从另一个数字中获取任意5位)。 >> 是一个错字:您需要使用它,因为常规abstract class AbstractHashCodeAccumulator<T> implements Accumulator<T, Integer> { private int accumulator = 0; abstract protected int combine(int a, int h); abstract protected int uncombine(int a, int h); @Override public void add(T t) { accumulator = combine(accumulator, t.hashCode()); @Override public void subtract(T t) { accumulator = uncombine(accumulator, t.hashCode()); @Override public Integer get() { return accumulator; } } class SumHasher extends AbstractHashCodeAccumulator<String> { @Override protected int combine(int a, int h) { return a+h; } @Override protected int uncombine(int a, int h) { return a-h; } } class XorHasher extends AbstractHashCodeAccumulator<String> { @Override protected int combine(int a, int h) { return a^h; } @Override protected int uncombine(int a, int h) { return a^h; } } 会执行符号扩展。糟糕,只有在set以相反的顺序删除。

编辑2 :最后,您可以更一般地实施此方法,如下所示:

{{1}}

这种方法的问题在于,它在某些方面是“非散列的”,即它需要有序性,而散列通常需要无序/熵/不可逆性。