我有一个应用程序,这显示收集的目的在行的一个对象=一行。的对象存储在一个哈希.所以行不影响该应用程序的功能(这就是为什么哈希被用于而不是排序收集的).

然而,我们注意到,相同的应用程序的运行方式不同运行时使用两个不同版本的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 执行情况的地图,应维持秩序。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top