是否有一些仅流的方法来确定最大流元素的索引?

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那个。

那太棒了。但我真正需要知道的是,这是第一次SetStream这最大?或者是10日SetStream?还是iSet?其中哪一个元素最多?

所以我的问题是:有没有一些方法-使用Stream API -我可以确定“这是iSetStreamSet传回他们所有的最大价值,为氏Set.size( )呼叫”?

我能想到的最佳解决方案是迭代Stream<Set<Integer>>(使用intSetStream.iterator())并进行手动max( )计算。但我希望学习更多Stream-y 的方法;如果有这样的事情。

Hol*_*ger 5

您可以使用自定义收集器执行此操作:

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)。它将两个部分评估的状态合并到第一个状态。如果第二个状态的最大值更大,我们更新第一个状态的最大值和位置,而我们必须将第一个状态的大小添加到第二个状态,以反映两者都是部分结果的事实。此外,我们必须将大小更新为两个大小的总和。

  • @deduper 你应该更频繁地留在 SO... :) Holger 的答案在这里最受赞赏,我工作的地方我们有一个名为 `xxx.HolgerUtil` 的完整包 - 主要是因为 1) 为什么不呢?2)我们拥有的东西只有因为他的回答才有可能 3)包文档以“如果您认为这是一个奇怪的类名称,那么您在这里工作的时间还不够长......” (2认同)
  • 有一个现有的内置收集器,[`summarizingInt`](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#summarizingInt-java.util.function.ToIntFunction -),它一次性提供计数和最大值(以及总和和最小值)。从那里,获得最大值的索引只是一小步。您也可以认为 `collect` 是最接近循环的操作,允许可变状态,具有用于初始化的 *supplier* 和执行循环体的 *accumulator*。新事物和最大障碍是部分结果的*组合器*。 (2认同)