浅析HashMap的存储数据无序性原因
众所周知,hashMap的put方法存储是无序的,不能根据自定义存放顺序来,如果需要有序则使用LinkedHashMap,如下面代码,
put时的顺序为:
12 -> 3 ->5 -> 16 -> 20 -> 21
循环遍历后的结果为:
16 -> 3 -> 20 -> 5 -> 21 -> 12
演示代码
public class HashMapTest {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap();
map.put(12,"abc");
map.put(3,"abc");
map.put(5,"abc");
map.put(16,"abc");
map.put(20,"abc");
map.put(21,"abc");
System.out.println("循环遍历结果:");
for(Integer key:map.keySet()){
System.out.print(key +" -> ");
}
}
}
循环遍历结果:
16 -> 3 -> 20 -> 5 -> 21 -> 12
但其实不管执行多少遍,每次遍历结果都是同样的顺序: 16 -> 3 -> 20 -> 5 -> 21 -> 12 ,并没有改变。
那么就要理解HashMap在put值时候怎么存放的问题,以及为什么每次遍历结果都相同?
如图所示,HashMap底层是数组+链表的结构,每个数组默认大小是16,即0-15,在put方法存放值的时候,会根据key值大小来计算存放位置,
12%16=12,3%16=3,5%16=5,16%16=0,20%16=4,21%16=5 因为key=5存放在前,key=21 存放在后,虽然余数都是5,因为插入数据先后顺序不同,所以 key=21 的数据链表悬挂在key=5之后。循环遍历的结果就是: 16 -> 3 -> 20 -> 5 -> 21 -> 12
数据存放如下图所示:
更改一下key=21与key=5插入顺序
put时的顺序为:
21 -> 12 -> 3 ->5 -> 16 -> 20
循环遍历后的结果为:
16 -> 3 -> 20 -> 21 -> 5 -> 12
演示代码
public class HashMapTest {
public static void main(String[] args) {
Map<Integer,String> map=new HashMap();
map.put(21,"abc");
map.put(12,"abc");
map.put(3,"abc");
map.put(5,"abc");
map.put(16,"abc");
map.put(20,"abc");
System.out.println("循环遍历结果:");
for(Integer key:map.keySet()){
System.out.print(key +" -> ");
}
}
}
循环遍历结果:
16 -> 3 -> 20 -> 21 -> 5 -> 12