为什么Java 8引入了iterable.forEach()循环(即使每个都有)?

时间:2018-06-25 04:18:05

标签: lambda foreach java-8

我不明白为什么Java 8具有forEach循环并以Consumer功能接口作为参数。即使我们可以为每个循环使用传统方法执行相同的任务,而无需创建任何额外的开销来创建一个类,该类实现了Consumer的实现,并实现了一个方法,然后将此作为参考传递给forEach()。尽管有lambda表达式可以使它简短。

Q1-为什么要迭代。forEach()?

Q2。在哪里使用?

Q3。对于Java 8 forEach()来说,哪种更快的是传统的?

示例:

pragma

4 个答案:

答案 0 :(得分:4)

受函数式编程启发的新API的一般思想是表达要做什么,而不是如何要做。即使使用简化的for-each循环,

for(Integer i: myList) System.out.println("Value::"+i);

这只是“获取Iterator实例并在其上反复调用hasNext()next()的说明的语法糖。”

相反,使用时

myList.forEach(i -> System.out.println("Value::"+i));

您提供了要应用于每个元素的操作,但未指定操作方法。 default实现只会执行基于Iterator的循环,但是实际的Iterable实现可能会覆盖它以不同方式执行操作。

请注意,许多Iterator实现都执行两次检查,一次是在hasNext()中,然后是再次在next()中进行,因为没有保证调用者会先执行hasNext() ,如果没有下一个元素,则抛出NoSuchElementException。有时,这甚至意味着在Iterator实例中保留其他状态,以记住是否已经执行了特定的“提取-下一个”操作。专用的forEach实现可以简单直接,更高效,同时简化代码。

例如,ArrayList执行基于int索引的循环而没有构造Iterator实例,Collections.emptyList()除了检查Consumer与{{ 1}},null分别。它的支持TreeSet遍历入口链接,这比其必须支持TreeMap操作的Iterator实现要简单得多,等等。

如果存在{({3}})(这是不可预见的)假设,那么专用的remove实现是否可以补偿forEach与构建有关的开销,并且对此的假设不应驱动软件设计。性能差异通常可以忽略不计。

但是在语义上也可能存在差异。使用Consumer返回的集合之一时,当基础集合被另一个线程修改时,基于Collections.synchronized…的循环无法提供一致性保证。应用程序需要手动锁定集合,并且必须注意使用正确的对象实例,例如如果迭代是not every lambda expression creates a new objectsubList。相反,专用的Iterator在整个操作过程中正确锁定,而操作本身就像委托源的forEach(Consumer)方法一样简单,仍然可以根据实际基础集合以最佳方式执行它

答案 1 :(得分:3)

这只是一个好问题。 如果您想要更多功能,请使用forEach,但对于您而言,传统的for-each循环是不错的选择。 实际上,for-loop支持两件事,forEach不支持:

  1. 流控制关键字,例如continuebreakreturn
  2. Checked exception

答案 2 :(得分:2)

Q1-为什么要迭代。forEach()?

它介绍减少代码行。您的循环可以按照旧方法和新方法进行查看

旧方式

   for (Integer t : myList) {
        System.out.println("forEach old way Value::"+t);
    }

新方法

   myList.forEach(t ->System.out.println("forEach lambda way::"+t));

Q2。在哪里使用?

要遍历集合的任何地方。

Q3。对于Java 8 forEach()来说,哪种更快的是传统的?

旧方法和新方法都没有很大的性能差异。但是,如果使用流进行迭代,则每个流都比旧流有一些延迟。

答案 3 :(得分:1)

forEach已创建为使用lambda语法:

myList.forEach(System.out::println);

myList.forEach(e->System.out.println(e));

这是功能界面的全部目的

相关问题