有一个简单的方法来一次提取流的最小值和最大值(基于一些比较器)?
似乎有许多方法可以单独获取最小值和最大值,也可以将流排序为临时对象,例如:
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(...).???
解决方法
如果这是一个经常需要的功能,我们最好让收藏家做这个工作.我们需要一个Stats类来保持count,min,max和factory方法来创建统计数据收集器.
Stats<String> stats = stringStream.collect(Stats.collector()) fooStream.collect(Stats.collector(fooComparator))
(也许更好的方便方法是Stats.collect(stream))
我举了一个例子Stats class –
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>> collector() { return collector(Comparator.naturalOrder()); } }