JDK 8 foreach的用法

forEach

      forEach 方法接收一个 Lambda 表达式,而后在 Stream 的每个元素上执行该表达式。java

清单  打印姓名(forEach 和 pre-java8 的对比)api

1多线程

2app

3函数

4性能

5优化

6线程

7设计

8code

9

10

// Java 8

roster.stream()

.filter(p -> p.getGender() == Person.Sex.MALE)

.forEach(p -> System.out.println(p.getName()));

// Pre-Java 8

for (Person p : roster) {

if (p.getGender() == Person.Sex.MALE) {

System.out.println(p.getName());

}

}

     对一我的员集合遍历,找出男性并打印姓名。能够看出来,forEach 是为 Lambda 而设计的,保持了最紧凑的风格。并且 Lambda 表达式自己是能够重用的,很是方便。当须要为多核系统优化时,能够 parallelStream().forEach(),只是此时原有元素的次序无法保证,并行的状况下将改变串行时操做的行为,此时 forEach 自己的实现不须要调整,而 Java8 之前的 for 循环 code 可能须要加入额外的多线程逻辑。

       但通常认为,forEach 和常规 for 循环的差别不涉及到性能,它们仅仅是函数式风格与传统 Java 风格的差异。

       另一点须要注意,forEach 是 terminal 操做,所以它执行后,Stream 的元素就被“消费”掉了,你没法对一个 Stream 进行两次 terminal 运算。下面的代码是错误的:

1

2

stream.forEach(element -> doOneThing(element));

stream.forEach(element -> doAnotherThing(element));

      相反,具备类似功能的 intermediate 操做 peek 能够达到上述目的。以下是出如今该 api javadoc 上的一个示例。

清单 peek 对每一个元素执行操做并返回一个新的 Stream

1

2

3

4

5

6

Stream.of("one", "two", "three", "four")

.filter(e -> e.length() > 3)

.peek(e -> System.out.println("Filtered value: " + e))

.map(String::toUpperCase)

.peek(e -> System.out.println("Mapped value: " + e))

.collect(Collectors.toList());

       forEach 不能修改本身包含的本地变量值,也不能用 break/return 之类的关键字提早结束循环。