当前位置: 首页 > 知识库问答 >
问题:

获取Java 8流的最小值和最大值的简明方法

乜昆
2023-03-14

是否有一种简洁的方法可以在一次过程中提取流的最小值和最大值(基于某个比较器)?

似乎有很多方法可以单独获取最小值和最大值,或者我可以将流排序为临时对象,例如:

List<T> sorted = Stream.of(...).sorted().collect(Collectors.toList());
T min = sorted.get(0);
T max = sorted.get(sorted.size() - 1);

但这并不简洁,需要分配一个临时对象。我宁愿不要分配一个临时对象,也不要在流中进行两次传递。有其他选择吗?

Pair<T> extent = Stream.of(...).???

共有3个答案

刁茂才
2023-03-14

将流的每个元素映射到一对,其中两个元素表示最小值和最大值;然后通过取最小值和最大值来减少对。

例如,使用一些配对类和一些比较器

Comparator<T> comparator = ...;
Optional<Pair<T, T>> minMax = list.stream()
    .map(i -> Pair.of(i /* "min" */, i /* "max" */))
    .reduce((a, b) -> Pair.of(
        // The min of the min elements.
        comparator.compare(a.first, b.first) < 0 ? a.first : b.first,
        // The max of the max elements.
        comparator.compare(a.second, b.second) > 0 ? a.second : b.second));
公冶同
2023-03-14

如果这是一项经常需要的功能,我们最好制作一个收集器来完成这项工作。我们需要一个Stats类来保存count、min、max和factory方法来创建Stats收集器。

Stats<String> stats = stringStream.collect(Stats.collector())

fooStream.collect(Stats.collector(fooComparator))

(也许更方便的方法是Stats.collect(stream))

我在课堂上做了一个例子-

https://gist.github.com/zhong-j-yu/ac5028573c986f7820b25ea2e74ed672

public class Stats<T>
{
    int count;

    final Comparator<? super T> comparator;
    T min;
    T max;

    public Stats(Comparator<? super T> comparator)
    {
        this.comparator = comparator;
    }

    public int count(){ return count; }

    public T min(){ return min; }
    public T max(){ return max; }

    public void accept(T val)
    {
        if(count==0)
            min = max = val;
        else if(comparator.compare(val, min)<0)
            min = val;
        else if(comparator.compare(val, max)>0)
            max = val;

        count++;
    }

    public Stats<T> combine(Stats<T> that)
    {
        if(this.count==0) return that;
        if(that.count==0) return this;

        this.count += that.count;
        if(comparator.compare(that.min, this.min)<0)
            this.min = that.min;
        if(comparator.compare(that.max, this.max)>0)
            this.max = that.max;

        return this;
    }

    public static <T> Collector<T, Stats<T>, Stats<T>> collector(Comparator<? super T> comparator)
    {
        return Collector.of(
            ()->new Stats<>(comparator),
            Stats::accept,
            Stats::combine,
            Collector.Characteristics.UNORDERED, Collector.Characteristics.IDENTITY_FINISH
        );
    }

    public static <T extends Comparable<? super T>> Collector<T, Stats<T>, Stats<T>> collector()
    {
        return collector(Comparator.naturalOrder());
    }
}
孔君浩
2023-03-14

如果您有整数流,汇总Int收集器可以很好地工作。

IntSummaryStatistics stats = Stream.of(2,4,3,2)
      .collect(Collectors.summarizingInt(Integer::intValue));

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

如果有Double,可以使用SummaringDouble收集器。

DoubleSummaryStatistics stats2 = Stream.of(2.4, 4.3, 3.3, 2.5)
  .collect(Collectors.summarizingDouble((Double::doubleValue)));
 类似资料:
  • 问题内容: 是否有一种简洁的方法可以一次性提取流的最小值和最大值(基于某个比较器)? 似乎有很多方法可以分别获取最小值和最大值,或者我可以将流分类为一个临时对象,例如: 但这并不简洁,需要分配一个临时对象。我宁愿不分配一个临时对象,也不希望两次通过流。有其他选择吗? 问题答案: 如果这是经常需要的功能,我们最好做一个。我们将需要一个类来保存,并需要使用工厂方法来创建统计收集器。 (也许更好的便捷方

  • 本文向大家介绍写一个获取数组的最大值、最小值的方法相关面试题,主要包含被问及写一个获取数组的最大值、最小值的方法时的应答技巧和注意事项,需要的朋友参考一下 es6

  • 问题内容: 我正在尝试编写一个查询,每天从价格明细表中获取每个商品的最低和最高价格。 在价格明细表中,每天设置多次价格,因此同一日期有很多记录。因此,我想要一个表,其中每个日期都有一行,然后将该表连接到同一张表,因此对于每个不同的日期,我都需要最小值和最大值。 SQL查询 概括 餐桌在同一天设定了许多价格。想要每个交易所报价的每天的最小值和最大值。 谢谢 问题答案: 一个简单的应该工作: 不知道为

  • 我有这样的课: 和类似的列表,其中填充了元素。 如何使用Java8获得的最小值和最大值?

  • 本文向大家介绍C#获取数组中最大最小值的方法,包括了C#获取数组中最大最小值的方法的使用技巧和注意事项,需要的朋友参考一下 根据下面函数获取数组中最大最小值即可。调用时候直接传数组范围一个float类型的变量