Java7中HashMap与Java5相比有什么变化

Java7中HashMap与Java5相比有什么变化,java,java-7,java-5,Java,Java 7,Java 5,我不是java专家,只是在Java5和Java7上体验以下程序输出的变化。有谁知道Java7在HashMap实现方面有什么变化吗 import java.util.HashMap; import java.util.Map; public class HashMapDemo { public static void main(String[] args) { Map<String, String> map = new HashMap<String, S

我不是java专家,只是在Java5和Java7上体验以下程序输出的变化。有谁知道Java7在HashMap实现方面有什么变化吗

import java.util.HashMap;
import java.util.Map;

public class HashMapDemo {
    public static void main(String[] args) {
        Map<String, String> map = new HashMap<String, String>();
        map.put("1", "111");
        map.put("a", "aaa");
        map.put("A", "AAA");

        map.put("D", "DDD");
        map.put("d", "ddd");
        map.put("0", "000");

        map.put("B", "BBB");
        map.put("b", "bbb");
        map.put("2", "222");

        for(Map.Entry<String, String> entry : map.entrySet()){
            System.out.println(entry.getKey()+ "  "+entry.getValue());
        }
    }
}
Java5上的输出

0  000
1  111
a  aaa
A  AAA
B  BBB
b  bbb
2  222
D  DDD
d  ddd

HashMap
是一个无序的集合。作为各州的Javadoc

此类不保证地图的顺序;特别是,它不能保证订单在一段时间内保持不变

如果您正在寻找反映任何类型订单的内容,请查看将保留插入订单的内容


更改顺序背后的原因很可能是哈希算法的更改

HashMap
不维护键的任何顺序,因此您不应该依赖这种顺序。上次我检查(Java 6实现)时,当迭代
HashMap
的条目时,会按顺序访问容器(即,容器0,然后是容器1等),并在每个容器中遍历条目的链接列表


在不检查Java 5和Java 7实现的情况下,我只能说不同的迭代顺序可能是由于
字符串
哈希代码
的更改、键的哈希代码映射到
哈希映射的bin的方式的更改或迭代顺序逻辑本身的更改造成的(我描述了Java 6的逻辑)。

散列算法发生了变化。这意味着您不能依赖
Java.util.HashMap
的迭代顺序。这并不奇怪,JDK从一开始就没有给出任何这样的保证。如果顺序对您很重要,请使用
TreeMap
LinkedHashMap

JDK5哈希映射:

static final int hash(Object key) {
   int h;
   return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
JDK7哈希映射:

final int hash(Object k) {
  int h = hashSeed;
  if (0 != h && k instanceof String) {
     return sun.misc.Hashing.stringHash32((String) k);
  }

  h ^= k.hashCode();
  // 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);
}

String
的函数
hashCode()
已更改,或者
HashMap
的内部结构已更改。但这又有什么关系呢?您绝对不应该对
HashMap
中元素的顺序有任何期望。随着时间的推移,在实现过程中发生了一些更改。您可以看到示例(GrepCode不维护Java5源代码的副本)。而在Java 8中,哈希算法又变回了Java 5版本!有一点历史:Java 7算法修复了一个漏洞,攻击者可能会通过造成大量冲突而导致
哈希映射的性能非常差。在Java 8中,引入了另一个修复方法,使用搜索树查找具有大量冲突的垃圾箱ns。这是非常好的信息。感谢分享。我一直想知道为什么他们在Java 7中更改了它,然后又在Java 8中更改了它。如果有人感兴趣,Java 9(撰写本文时的最新快照)中的算法与Java 5中的算法相同。
final int hash(Object k) {
  int h = hashSeed;
  if (0 != h && k instanceof String) {
     return sun.misc.Hashing.stringHash32((String) k);
  }

  h ^= k.hashCode();
  // 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);
}