开发中经常要使用到集合类Map,现在让我们来研究一下究竟有多少种遍历方法吧。
使用
遍历map时,我们想获得啥?
键值对?键?值?
贴心的Java已经定义了如下的三种方法供我们使用:
- entrySet():获取键值对集合,返回类型是Set
- keySet():获取键集合,返回类型是Set
- values():获取值集合,返回类型是Collection
由上面的返回类型可以知道,我们要遍历map,其实就是要遍历Collection,常用的遍历Collection方法:
- 增强型for
- 迭代器
-
Lambda
Map<String, Integer> map = new HashMap<>(); map.put(“firstElement”, 1); map.put(“secondElement”, 2);
// 使用for遍历 for(Map.Entry<String, Integer> entry : map.entrySet()) { System.out.println(“for-entry 键:” + entry.getKey() + “, 值:” + entry.getValue()); }
for(String k : map.keySet()) { System.out.println(“for-key 键:” + k + “, 值:” + map.get(k)); }
for(Integer v : map.values()) { System.out.println(“for-value 值:” + v); }
// 使用迭代器遍历 Iterator<Map.Entry<String, Integer» iterator = map.entrySet().iterator(); while (iterator.hasNext()) { Map.Entry<String, Integer> entry = iterator.next(); System.out.println(“iterator-entry 键:” + entry.getKey() + “, 值:” + entry.getValue()); }
Iterator
kIterator = map.keySet().iterator(); while (kIterator.hasNext()) { String key = kIterator.next(); System.out.println("iterator-key 键:" + key + ", 值:" + map.get(key)); } Iterator
vIterator = map.values().iterator(); while (vIterator.hasNext()) { Integer value = vIterator.next(); System.out.println("iterator-value 值:" + value); } // 使用Lambda map.forEach((k, v) -> { System.out.println(“Lambda-entry 键:” + k + “, 值:” + v); }); map.entrySet().forEach(entry -> { System.out.println(“Lambda-entry 键:” + entry.getKey() + “, 值:” + entry.getValue()); }); map.keySet().forEach(key -> System.out.println(“Lambda-key 键:” + key + “, 值:” + map.get(key))); map.values().forEach(value -> System.out.println(“Lambda-value 值:” + value));
entrySet()、keySet()和values()的作用
就像我们会遍历Collection集合一样,偶尔我们也会因业务需求遍历Map,但是Map的实现并不像Collection这么简单,底层是个数组或者链表什么的。
以HashMap为例,它的底层数据结构是:数组+链表+红黑树,这样作为开发者的我们就要花费大量精力去实现怎么遍历。
因此特意提供了entrySet()、keySet()和values()这三个方法,屏蔽底层的实现,提供简单易用的Collection。
3种遍历方法的本质
迭代器模式:提供一种方法顺序的访问一个聚合对象中各个元素,而又不暴露该对象的内部表示。
虽然上面提供了三种遍历方式,但其本质依然调用了迭代器:
- 增强型for循环,其底层是使用了iterator,这点可以通过编译后的代码可以了解到。
- 使用了Lambda表达式的forEach,其方法体内部依然是使用了增强型for循环。
通过使用迭代器我们就能轻易的访问集合对象而又无须关注集合对象的内部实现。