Map集合遍历
在程序开发中,经常需要取出Map中所有的键和值,那么如何遍历Map中所有的键值对呢?Map集合遍历的方式和单列集合Collection集合遍历的方式基本相同,主要有两种方式可以实现:第一种方式,可以使用Iterator迭代器遍历集合;第二种方式就是使用JDK 8提供的forEach(Consumer action)方法遍历集合。接下来,就以前面学习的HashMap集合为例来分别对这两种集合遍历方式进行详细讲解。
1.Iterator迭代器遍历Map集合
使用Iterator迭代器遍历Map集合,需要先将Map集合转换为Iterator接口对象,然后进行遍历,由于Map集合中元素是由键值对组成的,所以使用Iterator接口遍历Map集合时,会有两种将Map集合转换为Iterator接口对象再进行遍历的方法:keySet()方法和entrySet()方法。
其中,keySet()方法,需要先将Map集合中所有键对象转换为Set单列集合,接着将包含键对象的Set集合转换为Iterator接口对象,然后遍历Map集合中所有的键,再根据键获取相应的值。接下来就通过一个案例来演示先遍历Map集合中所有的键,再根据键获取相应的值的方式,如文件1所示。
文件1 Example15.java
1 import java.util.*;
2 public class Example15 {
3 public static void main(String[] args) {
4 Map map = new HashMap(); // 创建Map集合
5 map.put("1", "Jack"); // 存储元素
6 map.put("2", "Rose");
7 map.put("3", "Lucy");
8 System.out.println(map);
9 Set keySet = map.keySet(); // 获取键的集合
10 Iterator it = keySet.iterator(); // 迭代键的集合
11 while (it.hasNext()) {
12 Object key = it.next();
13 Object value = map.get(key); // 获取每个键所对应的值
14 System.out.println(key + ":" + value);
15 }
16 }
17 }
运行结果如图1所示。
图1 运行结果
文件1中,首先调用Map对象的KeySet()方法,获得存储Map集合中所有键的Set集合,然后通过Iterator迭代Set集合的每一个键元素,最后通过get(Objectkey)方法,根据键获取对应的值。
Map集合中的另外一种通过Iterator迭代器遍历集合的方式是使用entrySet()方法,该方法将原有Map集合中的键值对作为一个整体返回为Set集合,接着将包含键值对对象的Set集合转换为Iterator接口对象,然后获取集合中的所有的键值对映射关系,再从映射关系中取出键和值。接下来,将文件1中的第9~15行代码进行修改,通过使用entrySet()方法来进行Map集合遍历,修改后的代码示例如下所示:
import java.util.*;
public class Example15 {
public static void main(String[] args) {
Map map = new HashMap();
map.put("1", "Jack");
map.put("2", "Rose");
map.put("3", "Lucy");
System.out.println(map);
Set entrySet = map.entrySet();
Iterator it = entrySet.iterator(); // 获取Iterator对象
while (it.hasNext()) {
// 获取集合中键值对映射关系
Map.Entry entry = (Map.Entry) (it.next());
Object key = entry.getKey(); // 获取Entry中的键
Object value = entry.getValue(); // 获取Entry中的值
System.out.println(key + ":" + value);
}
}
}
再次运行文件1,运行结果如图2所示。
图2 运行结果
在上述修改的代码示例中,首先调用Map对象的entrySet()方法获得存储Map中所有键值映射的Set集合,这个集合中存放了Map.Entry类型的元素(Entry是Map接口内部类),每个Map.Entry对象代表Map中的一个键值对,然后迭代Set集合,获得每一个映射对象,并分别调用映射对象的getKey()和getValue()方法获取键和值。
2.JDK 8新方法遍历集合Map集合
与Collection集合遍历类似,在JDK 8中也根据Lambda表达式特性新增了一个forEach(BiConsumer action)方法来遍历Map集合,该方法所需要的参数也是一个函数式接口,因此可以使用Lambda表达式的书写形式来进行集合遍历。接下来通过一个案例来演示如何使用forEach(BiConsumer action)方法遍历Map集合,如文件2所示。
文件2 Example16.java
1 import java.util.HashMap;
2 import java.util.Map;
3 public class Example16 {
4 public static void main(String[] args) {
5 Map map = new HashMap();
6 map.put("1", "Jack");
7 map.put("2", "Rose");
8 map.put("3", "Lucy");
9 System.out.println(map);
10 // 使用JDK 8新增的forEach(BiConsumer action)方法遍历集合
11 map.forEach((key,value) -> System.out.println(key + ":" + value));
12 }
13 }
运行结果如图3所示。
图3 运行结果
文件2中,使用了JDK 8中Map集合新增的forEach(BiConsumer action)方法对集合中的元素进行遍历,该方法传递的是一个Lambda表达式书写的函数式接口BiConsumer。forEach(BiConsumer action)方法在执行时,会自动遍历集合元素的键和值并将结果逐个传递给Lambda表达式的形参。
在Map集合中,除了以上两种主要的遍历方式外,还提供了一个values()方法,通过这个方法可以直接获取Map中存储所有值的Collection集合,接下来通过一个案例来演示,如文件3所示。
文件3 Example17.java
1 import java.util.*;
2 public class Example17 {
3 public static void main(String[] args) {
4 Map map = new HashMap();
5 map.put("1", "Jack");
6 map.put("2", "Rose");
7 map.put("3", "Lucy");
8 System.out.println(map);
9 Collection values = map.values(); // 获取Map集合中value值集合对象
10 // 遍历Map集合所有值对象V
11 values.forEach(v -> System.out.println(v));
12 }
13 }
运行结果如图4所示。
图4 运行结果
在文件3中,通过调用Map的values()方法获取包含Map中所有值的Collection集合,然后迭代出集合中的每一个值。
多学一招:使用LinkedHashMap集合保证元素添加顺序
在前面小节介绍HashMap集合时,已经说明HashMap集合并不保证集合元素存入和取出的顺序。如果想让这两个顺序一致,可以使用Java中提供的LinkedHashMap类,它是HashMap的子类,和LinkedList一样也使用双向链表来维护内部元素的关系,使LinkedHashMap元素迭代的顺序与存入的顺序一致,接下来通过一个案例来学习一下LinkedHashMap的用法,如文件4所示。
文件4 Example18.java
1 import java.util.*;
2 public class Example18 {
3 public static void main(String[] args) {
4 Map map1 = new HashMap(); // 创建HashMap集合
5 map1.put(2, "Rose");
6 map1.put(1, "Jack");
7 map1.put(3, "Lucy");
8 map1.forEach((key,value) -> System.out.println(key + ":" + value));
9 System.out.println("=====================");
10 Map map2 = new LinkedHashMap(); // 创建LinkedHashMap集合
11 map2.put(2, "Rose");
12 map2.put(1, "Jack");
13 map2.put(3, "Lucy");
14 map2.forEach((key,value) -> System.out.println(key + ":" + value));
15 }
16 }
运行结果如图5所示。
图5 运行结果
在文件4中,分别创建了HashMap和LinkedHashMap两个集合,并按相同的顺序插入了相同的元素,然后使用forEach(BiConsumer action)方法将元素遍历取出。从运行结果可以看出,使用HashMap集合取出的元素并不能保证与存入元素顺序一致,而LinkedHashMap集合却可以保证存入和取出的一致性。
一般情况下,我们用的最多的是HashMap,在Map中插入、删除和定位元素,HashMap 是最好的选择。但如果需要输出的顺序和输入的相同,那么用LinkedHashMap可以实现,它还可以按读取顺序来排列。