一、foreach
1. 概述
- foreach 语法是在JDK 1.5时加入的新特性,可看作为增强for
2. foreach循环原理
- 使用 foreach 循环遍历,就必须正确地实现Iterable接口
- for循环是根据下标一个个检索获取,而foreach是通过迭代器Iterator,不断获取next元素,所以使用foreach,编译的时候编译器会自动将对for这个关键字的使用转化为对目标的迭代器的使用
- 引:
ArrayList之所以能使用foreach循环遍历,是因为所有的List都继承了Collection,而Collection又继承了Iterable,ArrayList的父类AbstractList正确地实现了Iterable接口的iterator方法
数组没有实现Iterable接口,但数组也可以使用 foreach 循环遍历,“因为Java将对于数组的 foreach 循环转换为对于这个数组每一个的循环引用”,这是网上的一种说法,简单来讲,就是数组使用 foreach 时,是把 foreach 转换为普通 for 来循环处理的
二、基本语法
for(元素类型 变量名 : 数组或集合){
System.out.println(变量名);
}
1. foreach数组测试
1.1 一维数组测试
public class Test {
public static void main(String[] args) {
int[] arr = { 1, 5, 15, 21, 9, 36, 13 };
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
System.out.println("===================");
for (int element : arr) {
System.out.println(element);
}
}
}
1.2 二维数组测试
public class Test {
public static void main(String[] args) {
int[][] arr = { { 1 }, { 33, 2 }, { 3, 4, 9, 46 } };
for (int e1[] : arr) {
for (int e2 : e1) {
System.out.println(e2);
}
}
}
}
2. foreach集合测试
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Test {
public static void main(String[] args) {
List<String> strList = new ArrayList<>();
strList.add("hello");
strList.add("world!");
Iterator<String> it = strList.iterator();
while(it.hasNext()){
String s = it.next();
System.out.println(s);
}
for(int i = 0; i < strList.size(); i++){
System.out.println(strList.get(i));
}
for(String s : strList){
System.out.println(s);
}
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(2);
list.add(3);
for(Integer i : list){
System.out.println(i);
}
}
}
三、foreach使用条件
- 使用 foreach 时对集合或数组中的元素不能做赋值操作
- foreach 同时只能遍历一个集合或数组
- foreach 遍历过程中,集合或数组中同时只有一个元素可见,即只有“当前遍历到的元素”可见,而前一个或后一个元素是不可见的
- 只能正向遍历,不能反向遍历
- 补充:ListIterator可以双向遍历
Iterator可以提供容器类的统一遍历方式,但当集合结构发生变化时,Iterator迭代器必须重新获取,尽管Iterator可以在遍历中使用remove方法删除元素,但是不能解决遍历时修改List的需求,而Iterator接口的子类ListIterator接口解决了这个问题,实现了遍历List的时候同时进行添加,修改的操作,即在Iterator的基础上添加了 prev 系列方法,实现了反向操作,并且添加了add和set方法 - ListIterator:
双向移动(向前/向后遍历),并产生相对于迭代器在列表中指向的当前位置的前一个和后一个元素的索引;
使用set()方法替换它访问过的最后一个元素;
使用add()方法在next()方法返回的元素之前或previous()方法返回的元素之后插入一个元素 - ListIterator与Iterator的区别
ListIterator 可以通过add()方法向List中添加对象,而Iterator不能;
ListIterator 和Iterator都有hasNext()和next()方法,可以实现顺序向后遍历,但是ListIterator有hasPrevious()和previous()方法,可以实现逆向/顺序遍历;
ListIterator 可以通过nextIndex()和previousIndex() 方法定位当前的索引位置;
ListIterator 可以在迭代时对集合进行add、set、remove操作,而Iterator迭代器只能在迭代时对集合进行 remove 操作
四、foreach与lambda表达式的使用
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) {
Map<Integer, String> map = new HashMap<>();
map.put(1, "星期一");
map.put(2, "星期二");
map.put(3, "星期三");
map.put(4, "星期四");
map.put(5, "星期五");
map.put(6, "星期六");
map.put(7, "星期日");
map.forEach((k, v) -> System.out.println("maps : " + k + " Count : " + v));
System.out.println("--------------------------");
map.forEach((k, v) -> {
System.out.println("maps : " + k + " Count : " + v);
});
}
}