使用 Stream 还是 Loop 之间的决定

Decision between using a Stream or a Loop

通过在 Java 中编写应用程序,java.util.Collection 有很多用例。 由于 java.util.stream.Stream 是在 Java 8 中引入的,我遇到了一些难以决定使用什么的用例。

例如: 您将要编写一些实用方法。

public static List<?> filterHashToList(int hash, Collection<?> toFilter) {
    return toFilter.stream()
        .filter((Object o) -> hash == o.hashCode())
        .collect(Collectors.toCollection(LinkedList::new));
}

这样写怎么样:

public static List<?> filterHashToList(int hash, Collection<?> toFilter) {
    List<Object> result = new LinkedList<>();

    for(Object o : toFilter) {
        if(hash == o.hashCode()) {
            result.add(o);
        }
    }

    return result;
}

两种方法都会产生相同的结果。 java.util.stream.Streamjava.util.stream.Collector 是接口,因此如果我使用自定义流和收集器,实现也会有所不同。

我认为有很多使用老式循环方式的实现。

那么,是否可以根据用例回答使用什么,流式传输或循环? 如果是这样,是否必须在适当的地方更新所有实施?

或者我是否应该通过实施 util-methods 来提供这两种方式? 或者我是否还应该提供一个在过滤过程后返回流的 mthed,以便您在需要时也可以使用该流?

在没有发布答案的情况下,我将引用 Brian Goetz 的观点,他与我的观点相呼应,我怀疑还有很多人的观点。

There's nothing magic about either streams or loops. You should write the code that is most readable, clear, and maintainable. Either of these are acceptable.

请注意,在您的实现中,您坚持使用特定的结果集合类型 LinkedList,与 ArrayList 相比,它的性能通常很差。如果您的方法的用户想要以随机访问方式使用结果列表怎么办?可能此方法的用户需要一个数组,因为它应该传递给另一个接受数组的 API 方法。有时用户只需要知道输入集合中有多少个具有给定 hashCode 的对象,因此根本不需要创建结果列表。 Java-8 方法是 return 来自方法的流,而不是集合,让调用者决定如何收集它:

public static <T> Stream<T> filterHashToList(int hash, Collection<T> toFilter) {
    return toFilter.stream()
        .filter(o -> hash == o.hashCode());
}

并使用它:

filterHashToList(42, input).count();

filterHashToList(42, input).collect(toCollection(ArrayList::new));

filterHashToList(42, input).toArray();

这样方法就变得很简单,所以你可能根本不需要它,但是如果你想做的更复杂filtering/transformation,没关系。

因此,如果您不想更改 API 而仍然 return LinkedList,则无需更改实施。但是如果你想利用 Stream API 的优势,最好将 return 类型更改为 Stream.

我认为这在很大程度上取决于 Collection 的预期大小和程序的实际应用。前者的效率稍高,但我发现它的可读性较差,并且在 Java 7 上仍有 运行 的系统(即 Google App Engine)。此外,后者可能更容易添加更复杂的过滤器以继续前进。但是,如果效率是首要考虑因素,我会选择前者。