我知道Java对HashMaps或HashTables有很好的内置支持。
是否有人知道Java语言使用了哪种散列函数或技术?
是否可以调整这些功能,以便能够使它们更适合某个应用程序,以提高性能并缩短访问时间?
非常感谢您的阅读!
答案 0 :(得分:11)
Java允许您覆盖类的hashCode()
方法,以使用不仅适合您的应用程序而且适合您的各种类型的散列算法:
public class Employee {
private int id;
// Default implementation might want to use "name" for as part of hashCode
private String name;
@Override
public int hashCode() {
// We know that ID is always unique, so don't use name in calculating
// the hash code.
return id;
}
}
答案 1 :(得分:4)
坚果。
http://www.docjar.com/html/api/java/util/HashMap.java.html
此外,您始终可以将调整大小阈值和初始内存使用量设置为您需要的大小,这将减少地图几乎已满时的放置时间。如果您的地图是线程化的,那么通过使用ConcurrentHashmap也可以获得巨大的性能提升。
答案 2 :(得分:4)
就像注意一样,如果你要覆盖hashCode,你也应该重写equals。
答案 3 :(得分:3)
根据存储在集合中的对象计算哈希码。它使用标准算法计算(根据Effective Java)。有关详细信息,请参阅。
您确实可以基于每个对象覆盖哈希码方法。实现hashcode方法的最佳方法是通过HashcodeBuilder(whcih是Commons Lang框架的一部分,请参见此处:
http://commons.apache.org/lang/
有关哈希码的更多详细信息,请参阅此文:
http://www.ibm.com/developerworks/java/library/j-jtp05273.html
希望有所帮助。
答案 4 :(得分:1)
我知道Java对HashMaps或HashTables有很好的内置支持。
完全缺乏哈希映射文字的语法,我真的不会说......
无论如何,正如其他人指出的那样,由各个类来指定他们的hashCode()应该是什么(默认是内存地址的散列)。如果你自己实现了,请确保遵循hashCode()方法的约定(特别是它需要与equals()一致),否则该类将不适用于HashMap中的键。
您还可以直接查看j ava.util.HashMap和朋友的源代码,看看它们是如何实现的。例如,HashMap使用一个桶数组,并且桶可以使用链表溢出。
为了进一步阅读,您可能希望查看ConcurrentHashMap,它可以被许多线程同时安全地访问,以及TreeMap,它提供了一种为可以订购的键构建映射的方法(而不是必然哈希)。
答案 5 :(得分:1)
一般来说,标准JDK类的哈希函数不值得担心。即使你可以覆盖String(你不能),实际上它的哈希函数实际上总是“足够好”。可能有一些例外 - 例如某些类(如BigInteger和collection)每次通过循环遍历它们包含的每个元素来计算它们的哈希码,这在某些情况下是非常虚假的 - 但是你多久键入一次这些类的实例?
为了设计自己类的哈希码,你要做的就是在整数范围内“随机”传播哈希码。为此,您通常希望“混合”对象中连续字段的位(您可能对我网站上的一篇文章感兴趣,该文章以图形方式说明how the String hash code mixes bits)。将当前散列乘以奇数(通常是素数),然后添加下一个元素的散列通常可以很好地作为第一次尝试。 (但是,例如,当组合的数字/哈希码往往在其较低位中具有零时,这种方法可能会出现问题 - 通常没有实际的哈希函数,绝对保证在所有情况下都能正常工作。)
然后,您可以考虑测试您的哈希码。生成一系列随机对象(甚至使用一些真实的对象),计算它们的哈希码,然后从底部开始,比如16位哈希码,然后看看你得到了多少次冲突。检查您获得的碰撞数量是否与hash collisions you'd expect to get by chance的数量大致匹配。例如,如果您在哈希代码(& 0xffff)的底部16位之后关闭,那么在1000个随机对象之后,您预计会发生大约8次冲突。 2000年之后,你会发现大约30次碰撞。
就性能而言,那么在某种程度上,我认为获得分布均匀的哈希码通常比牺牲散列计算速度的散列质量更有益。
答案 6 :(得分:1)
你应该遵守一个“hashCode / equals contract”,它表示根据equals()方法彼此相等的对象必须提供相同的hashCode()值。 然而,并不要求具有相同hashCode的所有对象也相等。您应该查看http://java.sun.com/javase/6/docs/api/java/lang/Object.html#hashCode(),它会告诉您详细信息。
最初可能有点难以理解所涉及的对称性,但绝对值得理解它,除非您在将对象放入HashMap和不使用HashMap的朋友时急于在应用程序中出现奇怪的行为坚持这份合同。
我还建议获取Effective Java的副本并阅读hashCode / equals的章节以完全理解它。
答案 7 :(得分:0)
我建议,如果你知道你需要快速哈希,那就是使用另一个实现:尝试快速util(http://fastutil.dsi.unimi.it/)或trove(http://trove4j.sourceforge.net/)。它们显然更快,但是类型特定。