Java中四种遍历集合的方法
迭代是集合中进行的基本操作之一。基本上,迭代是从一个到另一个集合

比如,你想在一个班级中遍历所有的学生打印出他们的名字或找到在最近的考试中的最高分是谁。或者你想遍历一组数字计算和或平均值。这样的操作在编程中是十分常见的。

Java提供了四种在集合上遍历的方法,包括循环,迭代和forEach(从Java 8开始)

before going to each kind of iteration, suppose that we have a List collection as follows:
在学习每种遍历方式之前,我们需要现有一组List集合:

public static void main(String[] args) {
         List<String> listNames = new ArrayList<>();
 
         listNames.add("qiuqiu");
         listNames.add("kaka");
         listNames.add("beibei");
         listNames.add("hutu");
         listNames.add("wangzai");
     }

This list contains names of all students in a class. Note that the diamond operator <> used in the right side of the assignment:
这个list包含我们小区的所有小狗的名字。注意在语句的右边<>的使用

ArrayList<>();
1
这个语法从Java7开始使用,允许我们以一种更严谨的方式声明泛型的集合,因为编译器可以从左边推测出右边的参数类型(因此叫做“类型引用”)

1. 经典循环方式
这种迭代方法在编程中非常熟悉,其中计数器变量从集合中的第一个元素运行到最后一个元素

1         for (int i = 0; i < listNames.size(); i++) {
2             String name = listNames.get(i);
3             System.out.println(name);
4         }

pros:
- 这是编程中最熟悉的构造
- 如果我们需要访问并使用计数器变量,比如打印小狗狗们的的数字顺序:1,2,3……

cons:
- 使用计数器变量要求集合必须以基于索引的形式(如ArrayList)存储元素,并且我们必须提前知道集合的大小

该集合必须提供一种通过基于索引的方式访问其元素的方法,这不是所有集合都支持的方式,例如, Set不会将元素存储为基于索引的元素。 因此这种方法不能用于所有集合。
2. 迭代的方式
由于经典循环方式的限制,创建了使用迭代器的方式,这种方式允许我们迭代各种集合。因此你可以看到Collection接口定义了每个集合必须实现iterator()方法

在List上用迭代器遍历:

1         Iterator<String> itr = listNames.iterator();
2 
3         while (itr.hasNext()) {
4             String name = itr.next();
5             System.out.println(name);
6         }

在Set上用迭代器遍历:

1         Set<String> set = new HashSet<>();
 2 
 3         set.add("a");
 4         set.add("b");
 5         set.add("c");
 6         set.add("d");
 7 
 8         Iterator<String> itr = set.iterator();
 9 
10         while (itr.hasNext()) {
11             String letter = itr.next();
12             System.out.println(letter);
13         }

在Map上用迭代器遍历:

1 Map<String, Integer> grade = new HashMap<>();
 2         grade.put("Operating System", 90);
 3         grade.put("Computer Network", 92);
 4         grade.put("Software Engineering", 90);
 5         grade.put("Oracle", 90);
 6         //Map迭代器
 7         Iterator<String> itr = grade.keySet().iterator();
 8         while (itr.hasNext()) {
 9             String key = itr.next();
10             Integer value = grade.get(key);
11             System.out.println(key + "=>" + value);
12         }
13         //Map迭代器2
14         Iterator<Map.Entry<String, Integer>> entries = grade.entrySet().iterator();
15         while (entries.hasNext()) {
16             Map.Entry<String, Integer> entry = entries.next();
17             System.out.println("Key = " + entry.getKey() + ", Value = " + entry.getValue());
18         }

3. 加强for循环
从Java 5开始,程序员可以使用一种更简洁的语法来遍历集合-加强for循环。

1         for (String s : listNames) {
2             System.out.println(s);
3         }

The enhanced for loop actually uses an iterator behind the scenes. That means the Java compiler will convert the enhanced for loop syntax to iterator construct when compiling. The new syntax just gives the programmers a more convenient way for iterating over collections.
注意:
加强for循环实际上在背后使用的是迭代器。这意味着编译时Java编译器会将增强型for循环语法转换为迭代器构造。 新的语法为程序员提供了一种更方便的迭代集合的方式。

4. 使用Lambda表达式的forEach
Java 8引入了Lambda表达式,介绍了一种遍历集合的全新方式-forEach方法

1         listNames.forEach(name -> System.out.println(name));

forEach方法与之前的方法最大的区别是什么?

在之前的方法中(经典for循环,迭代器和加强for循环),程序员可以控制集合是如何迭代的。迭代代码不是集合本身的一部分 - 它是由程序员编写的 - 因此称为外部迭代。
相比之下,新方法将迭代代码封装在集合本身中,因此程序员不必为迭代集合编写代码。 相反,程序员会在每次迭代中指定要做什么 - 这是最大的区别! 因此术语内部迭代:集合处理迭代本身,而程序员传递动作 - 即每次迭代需要做的事情。