每个`的Java8容器`和每个`的Stream`有什么区别

时间:2018-06-03 02:04:05

标签: java java-8 iteration

我知道我们可以使用List.foreach  遍历,我们也可以使用List.stream.foreach遍历。我不明白哪个更适合在Java8中遍历。

2 个答案:

答案 0 :(得分:5)

forEach(Consumer)方法在Iterable界面中声明Collection,因此List扩展。 forEach(Consumer)的默认实现是:

default void forEach(Consumer<? super T> action) {
    Objects.requireNonNull(action);
    for (T t : this) {
        action.accept(t);
    }
}

正如您所看到的,默认实现只是在for-each循环中调用action。 for-each循环只是语法糖:

for (Iterator<?> iterator = iterable.iterator(); iterator.hasNext(); ) {
    Object element = iterator.next();
    // Do what you need to with element
} 

除非您无法访问for-each循环中的Iterator

Iterable的具体实现可能会改变它实际迭代其元素的方式(它可能会也可能不会使用Iterator),但它几乎总是归结为某些{ {1}}或for循环。我说“几乎总是”,因为可能会涉及某种类型的递归或链接。

现在,当您只是尝试按顺序迭代while时,使用List.stream().forEach(Consumer)会创建一个不必要的Stream对象。如果您确实需要以管道方式处理元素集合(例如映射,过滤,映射更多等等),则应该只使用流API。

因此,对于简单的迭代,在几乎所有情况下,使用List的性能都不如简单的List.stream().forEach(Consumer)调用。性能提升很可能是微不足道的,但这是一个简单的解决方案,“优化”并不过分;特别是如果你没有首先犯“错误”。如果您不需要它们,请不要创建对象。

最好简单地使用for-each循环而不是List.forEach(Consumer)。它比功能更强大的对应物更容易阅读。

修改

正如Holger的评论中所提到的,forEach(Consumer)Stream.forEach(Consumer)有很大的不同:它确实不保证元素的遭遇顺序。虽然没有为Iterable.forEach(Consumer)接口定义Iterable.forEach(Consumer)的迭代顺序,但可以通过扩展接口(例如Iterable)来定义它。但是,使用List时,无论Stream的来源如何,都无法保证订单。

如果您希望在使用Stream时保证订单,则必须使用Stream

答案 1 :(得分:0)

请注意,尽管 <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <Button android:layout_width="48dp" android:layout_height="40dp" android:drawableBottom="@drawable/arrow_white_down" android:theme="@style/PasswordButton" /> <TextView android:id="@+id/TempNumb" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:paddingTop="0dp" android:text="8°C" android:textSize="30sp" /> <Button android:layout_width="48dp" android:layout_height="40dp" android:drawableBottom="@drawable/arrow_white_up" android:theme="@style/PasswordButton" /> </LinearLayout> 看起来与List.foreach类似,但它实际上并没有使用流式传输,所以它会在没有流式传输的情况下完成。

为了比较执行代码的复杂性,下面我将展示两种结构如何工作的缩写版本,通过删除验证逻辑简化了简化。

`List.foreach`

E.g。在List.stream.foreach中,这实现为:

ArrayList

就是这样。这真的很简单。

`List.stream.foreach`

这需要多种方法:

public void forEach(Consumer<? super E> action) {
    for (int i = 0; i < size(); i++)
        action.accept(get(i));
}

正如您所看到的,它会运行更多代码,并至少创建3个对象。