详情参看 oracle 官方文档: The For-Each Loop
Iterator 类提供的迭代方法:代码丑陋,Iterator 实例出现了三次容易出现错误
@Test
public void iteratorTest() {
List<String> names = this.createList();
for (Iterator<String> i = names.iterator(); i.hasNext();) {
LOGGER.debug("name is {}", i.next());
}
}
private List<String> createList() {
List<String> names = new ArrayList<>();
names.add("小明");
names.add("小强");
names.add("小红");
return names;
}
for-each 循环:代码简洁,避免实例变量的重复出现,规避了代码风险;
@Test
public void forEachNewTest() {
List<String> names = this.createList();
for (String name:names) {
LOGGER.debug("name is {}", name);
}
}
释义 :冒号可以看做是 " in.",上面的循环翻译过来就是 "for each String in names". for-each 循环 是和 泛型(generics)的完美结合,在保持类型安全的同时,移除了丑陋的代码:即不需要声明一个泛型,也不需要声明一个 Iterator 迭代器(编译器会自己处理)。
常见的 迭代器 Iterator 使用错误示例:
@Test
public void mistakeTest() {
List<String> names = this.createList();
List<String> fruits = this.createFruit();
List<Person> source = new ArrayList<>();
for (Iterator<String> i1 = names.iterator(); i1.hasNext();) {
for (Iterator<String> i2 = fruits.iterator(); i2.hasNext();) {
source.add(new Person(i1.next(), i2.next()));
}
}
}
private List<String> createList() {
List<String> names = new ArrayList<>();
names.add("小明");
names.add("小强");
names.add("小红");
names.add("小张");
return names;
}
private List<String> createFruit() {
List<String> fruits = new ArrayList<>();
fruits.add("apple");
fruits.add("orange");
return fruits;
}
private class Person {
private String name;
private String fruit;
public Person() {
}
public Person(String name, String fruit) {
this.name = name;
this.fruit = fruit;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getFruit() {
return fruit;
}
public void setFruit(String fruit) {
this.fruit = fruit;
}
}
最后生成的 source list 集合中只有四条数据,并不是我们想要的结果,原因是 外部集合(name)对应的 迭代器 的 next 方法被调用了太多次,内部集合(fruits) 和 外部集合(names) 对应的 迭代器对象的 next 方法 在 内部循环中都被调用。修复这个错误的示例代码:source 的 list 集合中有 8 个 对象。
@Test
public void mistakeFixTest() {
List<String> names = this.createList();
List<String> fruits = this.createFruit();
List<Person> source = new ArrayList<>();
for (Iterator<String> i1 = names.iterator(); i1.hasNext();) {
String name = i1.next();
for (Iterator<String> i2 = fruits.iterator(); i2.hasNext();) {
source.add(new Person(name, i2.next()));
}
}
}
for-each 循环是为 嵌套循环 而定制的,不会产生以上的错误:
@Test
public void mistakeForEachTest() {
List<String> names = this.createList();
List<String> fruits = this.createFruit();
List<Person> source = new ArrayList<>();
for (String name:names) {
for (String fruit:fruits) {
source.add(new Person(name, fruit));
}
}
LOGGER.debug("source size is {}", source.size());
}
for-each 循环 同样适用于 数组 ,当循环数组时,隐藏的是 数组的位置索引,而集合隐藏的是 迭代器对象。
使用 for-each 的好处有很多,美化代码,避免错误,但也不是所有的地方都能用 for-each 循环,例如,如果你想循环集合,并根据条件删除 或者 替换 集合中符合条件的元素时,因为不能调用到 Iterator 实例来 删除或者 替换,所以这种情况下不能使用 for-each 循环。另外,对于 并行遍历多个集合 循环也是不可用的。
@Test
public void filterTest() {
List<String> fruits = this.createFruit();
for (Iterator<String> i = fruits.iterator(); i.hasNext();) {
if (i.next().length() == 5) {
i.remove();
}
}
LOGGER.debug("fruits list size is {}", fruits.size());
}