Java默认使用什么散列函数,我们可以覆盖默认行为吗?

时间:2012-08-16 16:24:58

标签: java hash

我正在浏览Introduction of Algorithms by Cormen et al视频,并讨论了几种散列函数。我想知道Java默认使用什么散列函数?对于用作键的不同类型的对象,散列函数实际上是否有所不同? Collections框架中是否有api让我们编写自己的哈希算法?

5 个答案:

答案 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创建的一些(或多或少)唯一值(将其视为对象的内存地址,即使这并不完全正确)。当您实现自己的类时,您可以覆盖该方法以执行您想要的任何操作。但是,您应该注意您的hashCodeequals方法是一致的,并且您应该知道通常哈希码不是唯一的,因此无论您做什么,都希望不同对象的哈希码之间发生冲突。

Collections框架通常使用hashhCode()方法来散列Hashtables等的东西。可以想象其他库中的其他数据结构使用显式散列函数,但这不会发生在Collections框架中。