Java 7 对于 HashMap 从 Java 5 有什么变化
what has change in Java 7 for HashMap from Java 5
我不是 java 专家,只是在 Java 5 和 Java 7 上体验以下程序输出的变化。谁能知道发生了什么变化在 Java 7 中用于 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());
}
}
}
Java 7
上的输出
D DDD
2 222
d ddd
1 111
0 000
b bbb
A AAA
B BBB
a aaa
Java 5
上的输出
0 000
1 111
a aaa
A AAA
B BBB
b bbb
2 222
D DDD
d ddd
HashMap
是一个 无序 集合。作为 HashMap 状态的 Javadoc
This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
如果您正在寻找反映任何类型顺序的内容,请查看 LinkedHashMap
,它将保留插入顺序。
您更改订单背后的原因最可能是哈希算法的更改。
HashMap
不维护键的任何顺序,所以你不应该依赖这样的顺序。上次我检查(Java 6 实现)时,在遍历 HashMap
的条目时,按顺序访问 bin(即 bin 0,然后是 bin 1,等等...)并在每个 bin 遍历条目的链接列表。
在不检查 Java 5 和 Java 7 实现的情况下,我只能说不同的迭代顺序可能是 String
的 hashCode
,键的哈希码映射到 HashMap
的 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);
}
我不是 java 专家,只是在 Java 5 和 Java 7 上体验以下程序输出的变化。谁能知道发生了什么变化在 Java 7 中用于 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());
}
}
}
Java 7
上的输出D DDD
2 222
d ddd
1 111
0 000
b bbb
A AAA
B BBB
a aaa
Java 5
上的输出0 000
1 111
a aaa
A AAA
B BBB
b bbb
2 222
D DDD
d ddd
HashMap
是一个 无序 集合。作为 HashMap 状态的 Javadoc
This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.
如果您正在寻找反映任何类型顺序的内容,请查看 LinkedHashMap
,它将保留插入顺序。
您更改订单背后的原因最可能是哈希算法的更改。
HashMap
不维护键的任何顺序,所以你不应该依赖这样的顺序。上次我检查(Java 6 实现)时,在遍历 HashMap
的条目时,按顺序访问 bin(即 bin 0,然后是 bin 1,等等...)并在每个 bin 遍历条目的链接列表。
在不检查 Java 5 和 Java 7 实现的情况下,我只能说不同的迭代顺序可能是 String
的 hashCode
,键的哈希码映射到 HashMap
的 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);
}