我不明白为什么Java 8具有forEach循环并以Consumer功能接口作为参数。即使我们可以为每个循环使用传统方法执行相同的任务,而无需创建任何额外的开销来创建一个类,该类实现了Consumer的实现,并实现了一个方法,然后将此作为参考传递给forEach()。尽管有lambda表达式可以使它简短。
Q1-为什么要迭代。forEach()?
Q2。在哪里使用?
Q3。对于Java 8 forEach()来说,哪种更快的是传统的?
示例:
pragma
答案 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 object或subList
。相反,专用的Iterator
在整个操作过程中正确锁定,而操作本身就像委托源的forEach(Consumer)
方法一样简单,仍然可以根据实际基础集合以最佳方式执行它
答案 1 :(得分:3)
这只是一个好问题。
如果您想要更多功能,请使用forEach
,但对于您而言,传统的for-each循环是不错的选择。
实际上,for-loop
支持两件事,forEach
不支持:
continue
,break
,return
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));
这是功能界面的全部目的