「不保證有序」和「保證無序」不等價,HashSet的iterator是前者而不是後者,因此在一次運行中看到有序的結果也是正常的,但不能依賴這個有序行爲。
何況HashSet並不關心key的「排序」,就算其iterator「有序」一般也是說「按元素插入順序」(LinkedHashSet就支持插入順序遍歷)。題主在此看到的所謂「有序」純粹是個巧合。java
$ java SetOfInteger
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 16 19 18 21 20 23 22 25 24 27 26 29 28
$ java -version
java version "1.7.0-internal-zing_99.99.99.99.dev"
Zing Runtime Environment for Java Applications (build 1.7.0-internal-zing_99.99.99.99.dev-b65)
Zing 64-Bit Tiered VM (build 1.7.0-zing_99.99.99.99.dev-b870-product-azlinuxM-X86_64, mixed mode)
$ java SetOfInteger
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 17 16 19 18 21 20 23 22 25 24 27 26 29 28
$ java -version
java version "1.7.0_51"
Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)
$ java SetOfInteger
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$ java -version
java version "1.8.0-internal-zing_99.99.99.99.dev"
Zing Runtime Environment for Java Applications (build 1.8.0-internal-zing_99.99.99.99.dev-b65)
Zing 64-Bit Tiered VM (build 1.8.0-zing_99.99.99.99.dev-b870-product-azlinuxM-X86_64, mixed mode)
$ java SetOfInteger
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
就看到了題主說的有序行爲。linux
JDK8的HashSet實現變了,致使元素插入的位置發生了變化;iterator自身實現的順序倒沒變,仍是按照內部插入的位置順序來遍歷,因而題主就看到了JDK7和JDK8的結果不同。具體來講,是JDK7與JDK8的java.util.HashMap的hash算法以及HashMap的數據佈局發生了變化。算法
題主插入HashSet的是Integer,其hashCode()實現就返回int值自己。因此在對象hashCode這一步引入了巧合的「按大小排序」。$ cat SetOfInteger.java
import java.util.*;
public class SetOfInteger {
public static void main(String[] args){
Random rand=new Random(47);
Set<Integer> intset=new HashSet<Integer>();
for (int i=0;i<10000;i++){
intset.add(rand.nextInt(30) + (1 << 16));
}
Iterator<Integer> iterator=intset.iterator();
while (iterator.hasNext()){
System.out.print((iterator.next() - (1 << 16)) +" ");
}
}
}
$ java SetOfInteger
1 0 3 2 5 4 7 6 9 8 11 10 13 12 15 14 17 16 19 18 21 20 23 22 25 24 27 26 29 28
$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)