的项目顺序在哈希同时,同样的程序运行在JVM5vs JVM6
题
我有一个应用程序,这显示收集的目的在行的一个对象=一行。的对象存储在一个哈希.所以行不影响该应用程序的功能(这就是为什么哈希被用于而不是排序收集的).
然而,我们注意到,相同的应用程序的运行方式不同运行时使用两个不同版本的Java虚拟机。该应用程序编制使用JAVA5,并且可以运行所使用的Java5或Java6运行时,没有任何的功能性差别。
问题的对象复盖 java.lang.Object#hashCode()
显然已经采取谨慎措施,以按照合同中指定的Java API。这是证明了的事实,他们始终出现在同一顺序每次运行的应用程序(在同Java的运行时)。
出于好奇心的份上,为什么选择的Java运行,影响了?
解决方案
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);
}
作为参考,在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;
}
其他提示
大概是因为一个Map
并不限定为具有任何特定的迭代顺序;在其中元件回来的顺序可能是它的内部实现的伪影,而不需要以保持一致。
如果实施得到了Java 5和6(尤其是性能方面的原因)之间更新,也没有太阳的利益和义务,以确保迭代顺序保持两者之间是一致的。
修改:我刚刚发现了一个有趣的片段在早期的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);
}
如此看来,尽管我上面的说法,太阳的确在考虑迭代顺序的一致性 - 在以后的某个点这些代码可能下降,新订单做出明确的一个
哈希未结婚的任何特定订购,但是 LinkedHashMap 执行情况的地图,应维持秩序。
不隶属于 StackOverflow