dev*_*evv -2 java lambda reducing collectors
int val = integerList.stream().collect(
Collectors.reducing(0, a1 -> a1 * 5, (a1, a2) -> a1 + a2));
Run Code Online (Sandbox Code Playgroud)
上面的代码进行了归约操作。转换整数流和聚合函数以返回 Integer 。我无法理解以下代码和归约操作的内部实现。Java 如何执行以下有状态功能?谢谢!
java.util.stream.Collectors:reducing method
public static <T, U>
Collector<T, ?, U> reducing(U identity,
Function<? super T, ? extends U> mapper,
BinaryOperator<U> op) {
return new CollectorImpl<>(
boxSupplier(identity),
(a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
(a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
a -> a[0], CH_NOID);
}
Run Code Online (Sandbox Code Playgroud)
可能是,我会更好地澄清我的问题。上面的实现是如何获取数据流的。a[0],b[0] 是指数据流吗?我相信以上是为供应商和累加器提供功能实现。我想通过代码了解缩减过程是如何工作的。
该函数接受三个参数:
第一个是身份。减少流时,您必须从某个地方开始(否则,减少空列表的结果是什么?)。标识是应用于链中第一个归约操作的第一个参数的对象
第二个是映射器。reducing()
是一个广义操作 - 您可以将 type 流的元素减少为 typeT
的最终结果U
,因此您必须提供一个中间操作,该操作U
从 typeT
元素提供type元素。如果T == U
您不想进行转换,则可以在此处提供标识功能
第三个参数是归约函数 - 这是从标识开始按顺序应用于流元素的函数
所以,作为一个例子:
如果您只想将Integer
流的元素汇总为一个整数,则可以使用Collectors.reducing(0, x -> x, (x, y) -> x + y)
.
如果要汇总流中String
s的长度String
,可以使用Collectors.reducing(0, String::length, (x, y) -> x + y)
.
如果你想Double
从一串Double
s 中得到最大值,但不小于Math.PI
,你可以使用Collectors.reducing(Math.PI, x -> x, Math::max)
.
另外,如果你希望你的reduce是有状态的,请记住你可以将一个对象内部方法的引用用作reducor。这样,对象就可以用来保持状态。例如,这是一个“减税器”,每增加 100 次,它的分数就会增加 1 次“税”:
public class Taxer implements BinaryOperator<Integer> {
int counter = 0;
@Override
public Integer apply(Integer i1, Integer i2) {
counter++;
if (counter % 100 == 0) {
return i1 + i2 + 1;
} else {
return i1 + i2;
}
}
}
...
Taxer t = new Taxer();
...
.collect(Collectors.reducing(0, x -> x, t);
Run Code Online (Sandbox Code Playgroud)
同样可以扩展使用来实现复杂的情况,如groupingBy
:
Map<String, Integer> output = Stream.of("this", "word", "is", "the", "best")
.collect(Collectors.groupingBy(x-> x.substring(0, 1),
Collectors.reducing(0, x-> x.length(), (x, y)-> x + y)));
Run Code Online (Sandbox Code Playgroud)
这里首先输入字符串根据它们开始的字符分组,然后长度相加
归档时间: |
|
查看次数: |
5379 次 |
最近记录: |