我正在浏览Introduction of Algorithms by Cormen et al视频,并讨论了几种散列函数。我想知道Java默认使用什么散列函数?对于用作键的不同类型的对象,散列函数实际上是否有所不同? Collections框架中是否有api让我们编写自己的哈希算法?
答案 0 :(得分:7)
java中的每个对象都有一个返回哈希值的public int hashCode()
方法。每个对象都可以通过覆盖该方法以自己的方式自由地实现它。如果方法未被覆盖,则使用default Object#hashCode
method。
您可以查看各种对象的源代码,了解它在JDK中的实现方式。例如,这是String's hashCode(第1494行)。
某些集合可以在对象的hashCode方法之上添加额外的散列层。例如,当对象的hashCode分布不好时,HashMap会这样做以提高性能。
答案 1 :(得分:2)
您可以随时在任何课程中覆盖它...... 像
@override
public int hashCode()
{
//new implementation
}
http://mindprod.com/jgloss/hashcode.html
默认的hashCode()方法使用Object的32位内部JVM(Java虚拟机)地址作为其hashCode。
但是,如果在垃圾回收期间将Object移动到内存中,则hashCode保持不变。这个默认的hashCode不是很有用,因为要在HashMap中查找一个Object,你需要与键/值对最初归档的完全相同的密钥对象。
通常,当你去查找时,你没有原始的密钥对象本身,只有一些密钥的数据。因此,除非您的密钥是String,否则几乎总是需要在密钥类上实现hashCode和equals方法。
Object.hashCode()是一种本机方法。
答案 2 :(得分:1)
这取决于您使用的对象类型。对于您在自己的类中实现的任何对象,您始终可以覆盖默认的hashCode()方法。
注意,您应该始终遵守hashCode()javadoc中提到的hashCode()
和equals()
之间的合同:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须产生相同的整数结果。
有关详细信息,请参阅this entry。
答案 3 :(得分:0)
Java中的每个类型都定义了hashCode()
方法,就像它在Object
中一样。 hashCode()
会返回int
。在HashMap
实现中,它会再次散列结果并仅使用较低位使其在0到size
- 1的范围内。请注意,在Sun JDK中,大小始终为2 x ,x为某个整数。
Java库是开源的,你的dev机器上可能有一个副本。
在Sun JDK 6中,我上面提到的第二个哈希是
/**
* Applies a supplemental hash function to a given hashCode, which
* defends against poor quality hash functions. This is critical
* because HashMap uses power-of-two length hash tables, that
* otherwise encounter collisions for hashCodes that do not differ
* in lower bits. Note: Null keys always map to hash 0, thus index 0.
*/
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
您可以通过查看您感兴趣的班级上的hashCode()
函数找到第一个哈希值。
答案 4 :(得分:0)
Java中的所有类都继承自java.lang.Object
,通过这样做,它们继承了返回hashCode()
的方法int
。
默认方法返回VM创建的一些(或多或少)唯一值(将其视为对象的内存地址,即使这并不完全正确)。当您实现自己的类时,您可以覆盖该方法以执行您想要的任何操作。但是,您应该注意您的hashCode
和equals
方法是一致的,并且您应该知道通常哈希码不是唯一的,因此无论您做什么,都希望不同对象的哈希码之间发生冲突。
Collections框架通常使用hashhCode()
方法来散列Hashtables等的东西。可以想象其他库中的其他数据结构使用显式散列函数,但这不会发生在Collections框架中。