for 与 foreach 区别

4/26/2022 Java

心灵鸡汤

整理一下自己的心情,忘记那些不愉快的往事,听听音乐,看看风景,说能说的话,做可做的事,走该走的路,见想见的人

# 一:遍历














 




public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for (int i = 0; i < list.size(); i++) {
		System.out.println(list.get(i));
	}

	for (String string : list) {
		System.out.println(string);
	}

	String[] strings = new String[]{"3", "4", "5"};
	for (String string : strings) {
		System.out.println(string);
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

查看上面编译后的源码:








 










 






public static void main(String[] args) {
	List<String> list = (List)IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for(int i = 0; i < list.size(); ++i) {
		System.out.println((String)list.get(i));
	}

	Iterator var7 = list.iterator();

	while(var7.hasNext()) {
		String string = (String)var7.next();
		System.out.println(string);
	}

	String[] strings = new String[]{"3", "4", "5"};
	String[] var9 = strings;
	int var4 = strings.length;

	for(int var5 = 0; var5 < var4; ++var5) {
		String string = var9[var5];
		System.out.println(string);
	}

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

可见,foreach循环时,数组使用的还是原始 for 循环,集合使用的是 Iterator 迭代器。

# 二:删除元素

使用for循环

public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for (int i = 0; i < list.size(); i++) {
		list.remove("2");
	}

	System.out.println("List剩余元素个数:" + list.size());
	System.out.println("List剩余元素:" + list);
}
1
2
3
4
5
6
7
8
9
10
11

运行结果:

使用foreach:

public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for (String string : list) {
		list.remove("2");
	}

	System.out.println("List剩余元素个数:" + list.size());
	System.out.println("List剩余元素:" + list);
}
1
2
3
4
5
6
7
8
9
10
11

运行结果:

查看上面编译后的源码:

public static void main(String[] args) {
	List<String> list = (List)IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());
	Iterator var2 = list.iterator();

	while(var2.hasNext()) {
		String string = (String)var2.next();
		list.remove("2");
	}

	System.out.println("List剩余元素个数:" + list.size());
	System.out.println("List剩余元素:" + list);
}
1
2
3
4
5
6
7
8
9
10
11
12

运行报错,原因:

迭代器内部的每次遍历都会记录List内部的modcount当做预期值,然后在每次循环中用预期值与List的成员变量modCount作比较,但是普通list.remove调用的是List的remove,这时modcount++,但是iterator内记录的预期值=并没有变化,所以会报错。

所以,如果想要删除元素的话,需要使用迭代器内部的remove方法,如下所示:










 







public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	Iterator<String> it = list.iterator();
	while (it.hasNext()) {
		String next = it.next();
		if (next.equals("2")) {
			// 这里使用的是迭代器里面的remove()方法
			it.remove();
		}
	}

	System.out.println("List剩余元素个数:" + list.size());
	System.out.println("List剩余元素:" + list);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

运行结果:

如果条件简单的话,可以使用Lambda表达式:

public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	list.removeIf(next -> next.equals("2"));

	System.out.println("List剩余元素个数:" + list.size());
	System.out.println("List剩余元素:" + list);
}
1
2
3
4
5
6
7
8
9

使用的API Collection<E>:

















 







public interface Collection<E> extends Iterable<E> {
    /**
     * 删除此集合中满足给定Predicate的所有元素。在迭代期间或由Predicate引发的错误或运行时异常将转发给调用者。
     * @implSpec
     * 		默认实现使用其iterator遍历集合的所有元素。使用Iterator.remove()删除每个匹配元素。如果集合的迭代器不支持删除,则将在第一个匹配元素上抛出UnsupportedOperationException
     * @param filter 为要删除的元素返回true的Predicate
     * @return 如果删除了任何元素,则为true
     * @throws NullPointerException 如果指定的过滤器为空
     * @throws UnsupportedOperationException 如果无法删除匹配的元素,或者通常不支持删除,则实现可能会抛出此异常
     */
    default boolean removeIf(Predicate<? super E> filter) {
        Objects.requireNonNull(filter);
        boolean removed = false;
        final Iterator<E> each = iterator();
        while (each.hasNext()) {
            if (filter.test(each.next())) {
                each.remove();
                removed = true;
            }
        }
        return removed;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

运行结果:

# 三:修改元素

使用for:

public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for (int i = 0; i < list.size(); i++) {
		list.set(i, "123");
	}

	list.forEach(System.out::println);
}
1
2
3
4
5
6
7
8
9
10

运行结果:

使用foreach:

public static void main(String[] args) {

	List<String> list = IntStream.range(0, 3).mapToObj(String::valueOf).collect(Collectors.toList());

	for (String string : list) {
		string = "123";
	}

	list.forEach(System.out::println);
}
1
2
3
4
5
6
7
8
9
10

运行结果:

看结果,是无法修改了,那么如果修改元素的属性看是否可以?

创建一个学生类:

public class Student {

    private int id;

    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    public int getId() {
        return id;
    }

    public Student setId(int id) {
        this.id = id;
        return this;
    }

    public String getName() {
        return name;
    }

    public Student setName(String name) {
        this.name = name;
        return this;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                '}';
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37

测试代码:

public static void main(String[] args) {

	List<Student> list = IntStream.range(0, 3).mapToObj(id -> new Student(id, "张三" + id)).collect(Collectors.toList());

	for (Student student : list) {
		student.setName("李四" + student.getId());
	}

	list.forEach(System.out::println);
}
1
2
3
4
5
6
7
8
9
10

# 四:小结

  • for与foreach都可以遍历数组/集合,不过for则在较复杂的循环中效率更高。

  • foreach不可以删除/修改集合元素,而for可以

  • foreach和for都可以修改元素里面的属性

所以相比较下来for循环更为灵活

# 五:参考文献

最后更新: 5/12/2022, 10:27:49 AM