b/w foldLeft 和 Java collect 有什么区别

What's the difference b/w foldLeft and Java collect

此问题针对 Vavr(Java 的 FP 库),但可能适用于 Scala 或其他可以与 Java 相比的 FP 语言。

Vavr有什么区别foldLeft:

和Java的collect:

似乎两者都可以实现相同的目的:通过遍历集合并将结果累加到新类型U(或R)来转换集合(比如Stream<T>),而遍历.

乍一看,签名在#arguments 中有所不同,Java collect 似乎是 运行 并行块。

概念上有哪些实际差异? Vavr foldLeft 似乎更容易使用。

非常愚蠢的例子只是为了说明:

Vavr foldLeft:

// result = "HelloFunctionalWorld"
String result = Seq("Hello", "Functional", "World")
    .foldLeft(new StringBuilder(), (acc, word) -> acc.append(word))
    .toString();

Java collect:

// result = "HelloFunctionalWorld"
final String result = Arrays.asList("Hello", "Functional", "World").stream()
    .collect(
        StringBuilder::new,
        (acc, word) -> acc.append(word),
        StringBuilder::append
    )
    .toString();

Which are the actual differences conceptually?

正如 collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner) 的 javadoc 所说:

Performs a mutable reduction operation on the elements of this stream. A mutable reduction is one in which the reduced value is a mutable result container, such as an ArrayList, and elements are incorporated by updating the state of the result rather than by replacing the result. This produces a result equivalent to:

R result = supplier.get();
for (T element : this stream)
    accumulator.accept(result, element);
return result;

这里的关键词是可变,因为 Vavr 不做任何可变的事情,是一个功能库。

题目中使用StringBuilder的例子其实是违反函数式原则的。如果您不打算遵循功能范例,为什么要使用 Vavr?


Java 流相当于 foldLeft() is reduce(),你说得对,第三个参数是支持并行处理:

// Vavr
<U> U foldLeft​(U zero,
               BiFunction<? super U,​? super T,​? extends U> combine)

// Java Stream
<U> U reduce(U identity,
             BiFunction<U,? super T,U> accumulator,
             BinaryOperator<U> combiner)

如果结果类型与流元素类型相同,您将使用以下替代方案,不需要第三个参数来支持并行处理:

// Vavr
T fold​(T zero,
       BiFunction<? super T,​? super T,​? extends T> combine)

// Java Stream
T reduce(T identity,
         BinaryOperator<T> accumulator)

更新方法比较:

Vavr

Java 流