首页 > 解决方案 > b/w foldLeft 和 Java collect 有什么区别

问题描述

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

Vavr 和有什么区别foldLeft

和 Java 的collect

似乎两者都可以达到相同的目的:通过遍历集合来转换集合(比如Stream<T>),并在遍历时将结果累积为新类型U(或R)。

乍一看,#arguments 中的签名不同,Javacollect似乎打算在并行块中运行。

哪些是概念上的实际差异?VavrfoldLeft似乎更易于使用。

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

电压foldLeft

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

爪哇collect

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

标签: javascalajava-streamvavr

解决方案


哪些是概念上的实际差异?

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

对此流的元素执行可变归约操作。可变归约是一种归约值是一个可变结果容器,例如ArrayList, 并且通过更新结果的状态而不是替换结果来合并元素。这会产生等效于:

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

这里的关键词是mutable,因为 Vavr 不做任何可变的事情,它是一个函数库。

问题中的示例 usingStringBuilder实际上违反了功能原则。如果您不打算遵循功能范式,为什么要使用 Vavr?


Java Stream 等价于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)

更新方法比较:

电压

Java 流


推荐阅读