bgu*_*uiz 7 java hashmap hashcode
我有一个应用程序,它显示行中的对象集合,一个对象=一行.对象存储在HashMap中.行的顺序不会影响应用程序的功能(这就是使用HashMap而不是可排序集合的原因).
但是我注意到,当使用两个不同版本的Java虚拟机运行时,相同的应用程序运行方式不同.应用程序使用JDK 5编译,可以使用Java 5或Java 6运行时运行,没有任何功能差异.
有问题的对象覆盖java.lang.Object#hashCode()并且显然需要遵循Java API中指定的契约.这可以通过以下事实得到证明:它们在应用程序的每次运行中始终以相同的顺序出现(在同一Java运行时中).
出于好奇,为什么Java运行时的选择会影响订单?
Mic*_*rdt 17
HashMap可以改变的实施细节.这个包私有方法最有可能(这是来自JDK 1.6.0_16):
/**
* 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);
}
Run Code Online (Sandbox Code Playgroud)
作为参考,JDK 1.5.0_06中的模拟是:
/**
* Returns a hash value for the specified object. In addition to
* the object's own hashCode, this method applies a "supplemental
* hash function," which defends against poor quality hash functions.
* This is critical because HashMap uses power-of two length
* hash tables.<p>
*
* The shift distances in this function were chosen as the result
* of an automated search over the entire four-dimensional search space.
*/
static int hash(Object x) {
int h = x.hashCode();
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
Run Code Online (Sandbox Code Playgroud)
And*_*yle 10
可能是因为a Map未定义为具有任何特定的迭代顺序; 元素返回的顺序可能是其内部实现的工件,并且不需要保持一致.
如果在Java 5和6之间更新实现(特别是出于性能原因),Sun没有任何好处或义务确保迭代顺序在两者之间保持一致.
编辑:我刚刚在Java 6早期版本中发现了一个有趣的片段(不幸的是我不确定它的确切版本,但显然是2006年6月的HashMap 1.68):
/**
* Whether to prefer the old supplemental hash function, for
* compatibility with broken applications that rely on the
* internal hashing order.
*
* Set to true only by hotspot when invoked via
* -XX:+UseNewHashFunction or -XX:+AggressiveOpts
*/
private static final boolean useNewHash;
static { useNewHash = false; }
private static int oldHash(int h) {
h += ~(h << 9);
h ^= (h >>> 14);
h += (h << 4);
h ^= (h >>> 10);
return h;
}
private static int newHash(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);
}
Run Code Online (Sandbox Code Playgroud)
所以看起来尽管我上面的断言,Sun实际上确实考虑了迭代顺序的一致性 - 在稍后的某个时候,这个代码可能会被丢弃,而新的命令也是最终的.
| 归档时间: |
|
| 查看次数: |
2662 次 |
| 最近记录: |