ded*_*per 2 java-8 java-stream
我有一个Stream<Set<Integer>> intSetStream.
我可以这样做...
Set<Integer> theSetWithTheMax = intSetStream.max( (x,y)->{ return Integer.compare( x.size(), y.size() ); } ).get( );
Run Code Online (Sandbox Code Playgroud)
...我掌握了其中元素Set<Integer>数量最多的Integer那个。
那太棒了。但我真正需要知道的是,这是第一次Set在Stream这最大?或者是10日Set在Stream?还是i第Set?其中哪一个元素最多?
所以我的问题是:有没有一些方法-使用Stream API -我可以确定“这是i个Set在Stream中Set传回他们所有的最大价值,为氏Set.size( )呼叫”?
我能想到的最佳解决方案是迭代Stream<Set<Integer>>(使用intSetStream.iterator())并进行手动max( )计算。但我希望学习更多Stream-y 的方法;如果有这样的事情。
您可以使用自定义收集器执行此操作:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new int[] { 0, -1, -1 },
(a,i) -> { int pos = a[0]++; if(i>a[2]) { a[1] = pos; a[2] = i; } },
(a1,a2) -> {
if(a2[2] > a1[2]) { a1[1] = a1[0]+a2[1]; a1[2] = a2[2]; }
a1[0] += a2[0];
})[1];
Run Code Online (Sandbox Code Playgroud)
这是最轻量级的解决方案。当我们使用专用类而不是数组时,它的逻辑变得更加清晰:
int posOfMax = stream.mapToInt(Set::size)
.collect(() -> new Object() { int size = 0, pos = -1, max = -1; },
(o,i) -> { int pos = o.size++; if(i>o.max) { o.pos = pos; o.max = i; } },
(a,b) -> {
if(b.max > a.max) { a.pos = a.size+b.pos; a.max = b.max; }
a.size += b.size;
}).pos;
Run Code Online (Sandbox Code Playgroud)
状态对象保存大小,它只是到目前为止遇到的元素的数量,最后遇到的最大值及其位置,如果当前元素大于最大值,我们将更新为大小的前一个值。这就是accumulator函数( 的第二个参数collect)所做的。
为了支持任意求值顺序,即并行流,我们必须提供一个组合器函数(最后一个参数collect)。它将两个部分评估的状态合并到第一个状态。如果第二个状态的最大值更大,我们更新第一个状态的最大值和位置,而我们必须将第一个状态的大小添加到第二个状态,以反映两者都是部分结果的事实。此外,我们必须将大小更新为两个大小的总和。
| 归档时间: |
|
| 查看次数: |
257 次 |
| 最近记录: |