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

2024-03-26

我有一个Stream<Set<Integer>> intSetStream.

我可以用它来做这个...

Set<Integer> theSetWithTheMax = intSetStream.max( (x,y)->{ return Integer.compare( x.size(), y.size() ); } ).get( );

...我掌握了Set<Integer>拥有最多数量的Integer其中的元素。

那太棒了。但我真正需要知道的是,这是第一个吗?Set在那里面Stream这是最大值吗?或者是第10个Set in the Stream?或者ith Set?其中哪一个元素最多?

所以我的问题是:有什么办法——使用流 API——我可以确定“这是ith Set in the Stream of Set返回其中最大值的 s,对于Set.size( ) call"?

我能想到的最好的解决方案是迭代Stream<Set<Integer>> (using 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];

这是最轻量级的解决方案。当我们使用专用类而不是数组时,它的逻辑变得更加清晰:

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;

状态对象保存大小,它只是到目前为止遇到的元素数量、最后遇到的最大值及其位置,如果当前元素大于最大值,我们将其更新为先前的大小值。这就是累加器函数(第二个参数collect) does.

为了支持任意评估顺序,即并行流,我们必须提供combiner函数(最后一个参数collect)。它将两个部分评估的状态合并到第一个状态。如果第二个状态的最大值更大,我们更新第一个状态的最大值和位置,而我们必须将第一个状态的大小添加到第二个状态的位置以反映两者都是部分结果的事实。此外,我们必须将大小更新为两个大小的总和。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

是否有某种仅流的方法来确定最大流元素的索引? 的相关文章

随机推荐