首先HashMap中的keySet是有序的。
输入代码:
@Test public void testMapSort(){ Map<Integer, Integer> map = new HashMap<>(); map.put(1,1); map.put(2,2); map.put(3,3); map.put(4,4); map.put(5,5); map.put(6,6); map.put(7,7); map.put(8,8); for (Map.Entry<Integer, Integer> i : map.entrySet()) { System.out.println("k:"+i.getKey()+"-------------v:"+i.getValue()); } }
输出:
k:1-------------v:1 k:2-------------v:2 k:3-------------v:3 k:4-------------v:4 k:5-------------v:5 k:6-------------v:6 k:7-------------v:7 k:8-------------v:8
将2,2和3,3顺序颠倒一下:
@Test public void testMapSort(){ Map<Integer, Integer> map = new HashMap<>(); map.put(1,1); map.put(3,3); map.put(2,2); map.put(4,4); map.put(5,5); map.put(6,6); map.put(7,7); map.put(8,8); for (Map.Entry<Integer, Integer> i : map.entrySet()) { System.out.println("k:"+i.getKey()+"-------------v:"+i.getValue()); } }
输出:
k:1-------------v:1 k:2-------------v:2 k:3-------------v:3 k:4-------------v:4 k:5-------------v:5 k:6-------------v:6 k:7-------------v:7 k:8-------------v:8
结论:
可以发现entrySet具有无序性。
那么keySet呢?
@Test public void testMapSort(){ Map<Integer, Integer> map = new LinkedHashMap<>(); map.put(1,1); map.put(3,3); map.put(2,2); map.put(4,4); map.put(5,5); map.put(6,6); map.put(7,7); map.put(8,8); System.out.println("-----------------------------------keySet---------------------------"); for (Integer key : map.keySet()) { System.out.println("k:"+key+"-------------v:"+map.get(key)); } }
输出:
-----------------------------------keySet--------------------------- k:1-------------v:1 k:3-------------v:3 k:2-------------v:2 k:4-------------v:4 k:5-------------v:5 k:6-------------v:6 k:7-------------v:7 k:8-------------v:8
颠倒顺序:
@Test public void testMapSort(){ Map<Integer, Integer> map = new LinkedHashMap<>(); map.put(1,1); map.put(2,2); map.put(3,3); map.put(4,4); map.put(5,5); map.put(6,6); map.put(7,7); map.put(8,8); System.out.println("-----------------------------------keySet---------------------------"); for (Integer key : map.keySet()) { System.out.println("k:"+key+"-------------v:"+map.get(key)); } }
输出:
-----------------------------------keySet--------------------------- k:1-------------v:1 k:2-------------v:2 k:3-------------v:3 k:4-------------v:4 k:5-------------v:5 k:6-------------v:6 k:7-------------v:7 k:8-------------v:8
结论:
keySet()可以保证有序,即可以按照put到map中的顺序遍历。
但entrySet()并不能保证有序性,不能按照put到map中的顺序遍历。
所以:
如果想保证遍历map的有序性:
- 使用keySet进行遍历map中的元素。
- 使用LinkedHashMap遍历entrySet。
如果想保证entrySet有序性的话,建议使用LinkedHashMap:
@Test public void testMapSort(){ Map<Integer, Integer> map = new LinkedHashMap<>(); map.put(1,1); map.put(3,3); map.put(2,2); map.put(4,4); map.put(5,5); map.put(6,6); map.put(7,7); map.put(8,8); for (Map.Entry<Integer, Integer> i : map.entrySet()) { System.out.println("k:"+i.getKey()+"-------------v:"+i.getValue()); } }
输出:
k:1-------------v:1 k:3-------------v:3 k:2-------------v:2 k:4-------------v:4 k:5-------------v:5 k:6-------------v:6 k:7-------------v:7 k:8-------------v:8
另外补充:使用
map.forEach((k, v) -> { }); 这样的写法并不能保证map的遍历有序性,因为map重写了forEach方法,底层也是根据entrySet遍历的,所以,如果想用forEach遍历的话,推荐使用LinkedHashMap。 map的底层代码:
default void forEach(BiConsumer<? super K, ? super V> action) { Objects.requireNonNull(action); for (Map.Entry<K, V> entry : entrySet()) { K k; V v; try { k = entry.getKey(); v = entry.getValue(); } catch(IllegalStateException ise) { // this usually means the entry is no longer in the map. throw new ConcurrentModificationException(ise); } action.accept(k, v); } }