如何使用流(streams)获取嵌套集合中的最小/最大元素,避免冗余代码?

huangapple go评论82阅读模式
英文:

How to get the min/max element of nested collections without redundant code using streams?

问题

例如:

给定一个 Set<Set<Integer>>,我已经尝试使用

int min = nestedSets.stream().map(s->s.stream().min(Comparator.naturalOrder()).get()).min(Comparator.naturalOrder()).get();

我的初始想法是使用 flatMap,然而它并没有返回所期望的结果。

英文:

For example:

Given a Set&lt;Set&lt;Integer&gt;&gt;, I have tried to use

int min = nestedSets.stream().map(s-&gt;s.stream().min(Comparator.naturalOrder()).get()).min(Comparator.naturalOrder()).get();

My initial idea was to use flatMap, however it doesn't returns the desired result.

答案1

得分: 2

你可以将元素收集到 IntSummaryStatistics 中,它是:

> 用于收集统计信息,如计数、最小值、最大值、总和和平均值的状态对象。

例如:

Set&lt;Set&lt;Integer&gt;&gt; set = ...;

IntSummaryStatistics stats =
    set.stream()                      // Stream&lt;Set&lt;Integer&gt;&gt;
        .flatMap(Set::stream)         // Stream&lt;Integer&gt;
        .mapToInt(Integer::intValue)  // IntStream
        .summaryStatistics();         // IntSummaryStatistics

int min = stats.getMin();
int max = stats.getMax();

如果没有记录任何值,#getMin() 返回 Integer.MAX_VALUE#getMax() 返回 Integer.MIN_VALUE

英文:

You can collect the elements into an IntSummaryStatistics, which is:

>A state object for collecting statistics such as count, min, max, sum, and average.

For example:

Set&lt;Set&lt;Integer&gt;&gt; set = ...;

IntSummaryStatistics stats =
    set.stream()                      // Stream&lt;Set&lt;Integer&gt;&gt;
        .flatMap(Set::stream)         // Stream&lt;Integer&gt;
        .mapToInt(Integer::intValue)  // IntStream
        .summaryStatistics();         // IntSummaryStatistics

int min = stats.getMin();
int max = stats.getMax();

If no values were recorded then #getMin() returns Integer.MAX_VALUE and #getMax() returns Integer.MIN_VALUE.

答案2

得分: 2

Sure, here's the translated code:

Set<Set<Integer>> nestedSets = ...;

IntSummaryStatistics stats = nestedSets.stream()
                                       .flatMap(Set::stream)
                                       .mapToInt(Integer::intValue)
                                       .summaryStatistics();

stats.getMax();
stats.getMin();
英文:
    Set&lt;Set&lt;Integer&gt;&gt; nestedSets = ...

    IntSummaryStatistics stats = nestedSets.stream()
                                           .flatMap(Set::stream)
                                           .mapToInt(Integer::intValue)
                                           .summaryStatistics();

    stats.getMax();
    stats.getMin();

答案3

得分: 1

返回类型应为OptionalInt,因为您不知道是否找到了最小值。您可以执行以下操作:

OptionalInt min = nestedSets.stream()
    .flatMap(Set::stream)
    .mapToInt(Integer::intValue)
    .min();

或者,您可以在Stream::min中使用具有相同映射函数(Integer::intValue)的Comparator,这会导致装箱的Optional<Integer>

Optional<Integer> min = nestedSets.stream()
    .flatMap(Set::stream)
    .min(Comparator.comparingInt(Integer::intValue));

这取决于您是否需要所有这些值,或者只需要minmax之一。

  • 优点: 我认为这些解决方案易于阅读,没有冗余代码,是计算最小值/最大值/平均值等的最佳方法。

  • 缺点: 您一次只能计算一个值(minmax)。否则,如前面已经在此处回答的那样,用IntSummaryStatistics进行汇总计算。

英文:

The returned type should be OptionalInt since you don't know it the minimum value is found. You can do:

OptionalInt min = nestedSets.stream()
    .flatMap(Set::stream)
    .mapToInt(Integer::intValue)
    .min();

Alternatively, you can use Comparator with the very same mapping function (Integer::intValue) inside Stream::min which results in boxed Optional&lt;Integer&gt; instead:

Optional&lt;Integer&gt; min = nestedSets.stream()
    .flatMap(Set::stream)
    .min(Comparator.comparingInt(Integer::intValue));

It depends if you need all these values or just either min or max.

  • Pros: I find these solutions easy to read, with no redundant code and the best way to compute min/max/avg or more.

  • Cons: You can compute only one value (either min or max) at the same time. Use IntSummaryStatistics for summary computations otherwise as already answered here.

huangapple
  • 本文由 发表于 2020年4月7日 21:58:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/61081743.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定