java - b/w foldLeft 和 Java collect 有什么区别
问题描述
此问题针对Vavr(Java 的 FP 库),但可能适用于 Scala 或其他可以与 Java 相比较的 FP 语言。
Vavr 和有什么区别foldLeft
:
-
<U> U foldLeft(U zero, BiFunction<? super U, ? super T, ? extends U> combiner)
和 Java 的collect
:
-
<R> R collect(Supplier<R> supplier, BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner)
似乎两者都可以达到相同的目的:通过遍历集合来转换集合(比如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();
解决方案
哪些是概念上的实际差异?
正如 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)
更新方法比较:
电压
T fold(T zero, BiFunction<? super T,? super T,? extends T> combine)
以任意顺序应用
combine
,因此它必须是关联函数。<U> U foldLeft(U zero, BiFunction<? super U,? super T,? extends U> combine)
从左到右应用值。
相当于
reduce(identity, accumulator, combiner)
在顺序模式下,其中combiner
未使用。有效功能支持的并行模式。combiner
<U> U foldRight(U zero, java.util.function.BiFunction<? super T,? super U,? extends U> combine)
从右到左应用值。
没有等效的 Java 流。
Java 流
Optional<T> reduce(BinaryOperator<T> accumulator)
以任意顺序应用
accumulator
,因此它必须是关联函数。例如流式1,2,3,4
处理+
可以被处理为((1+2)+3)+4
(顺序模式),或(1+2)+(3+4)
,1+((2+3)+4)
或任何顺序组合(并行模式)。没有等效的 Vavr。
T reduce(T identity, BinaryOperator<T> accumulator)
以任意顺序应用
accumulator
,因此它必须是关联函数。例如,流式传输1,2,3,4
和0
可以+
被处理为(((0+1)+2)+3)+4
(顺序模式),((0+1)+2) + ((0+3)+4)
或任何顺序组合(并行模式)。<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner)
按顺序应用值,并
combiner
提供对并行处理的支持。顺序模式等价于foldLeft(zero, combine)`。
<R> R collect(Supplier<R> supplier, BiConsumer<R,? super T> accumulator, BiConsumer<R,R> combiner)
在顺序模式下,
supplier
用于创建可变结果容器,然后按顺序应用值。在并行模式下,创建多个可变结果容器并用值填充,然后使用该combiner
函数进行合并。没有等效的 Vavr。
推荐阅读
- javascript - 获取嵌入式 Tableau 仪表板的窗口高度
- php - 如何通过 PHP 的缩短 URL 找到一系列重定向后的最后一个(最终)URL
- postgresql - postgres中具有Hamming差异的唯一约束
- html - NVDA 不读取 Firefox 导航中的链接或标题属性,或屏幕阅读器文本
- database - 是否可以在 Oracle Express Edition 中使用保存点和回滚?
- c# - 不支持关键字:尝试打开 SQL 连接时出现“提供者”
- php - php访问变量
- javascript - 将元素添加到数组的末尾
- javascript - ReactJS:尝试打印我的数组对象的索引 - 如果我删除元素,它应该动态变化
- c++ - 无法让 `std::enable_if` 为无作用域枚举工作