另一种解决方案是使用相同的收集步骤同时计算最小值和最大值。为此,我们可以从 IntSummaryStatistics 类中启发自己,并构造一个 ObjectSummaryStatistics 来保存最小值和最大值。
对于您的特定用例而言,此解决方案可能太多了。仅当您发现自己经常这样做时,它可能会很方便。
最小值和最大值初始化为null,并在每次接受元素或进行组合时更新。我使用Optionals 作为返回值,以与常见的min 和max 操作的API 返回值一致。
public class ObjectSummaryStatistics<T> implements Consumer<T> {
private long count;
private T min;
private T max;
private Comparator<T> comparator;
public ObjectSummaryStatistics(Comparator<T> comparator) {
this.comparator = Objects.requireNonNull(comparator, "A comparator must be set");
}
@Override
public void accept(T t) {
min = count == 0 ? t : min(min, t);
max = count == 0 ? t : max(max, t);
count++;
}
public void combine(ObjectSummaryStatistics<T> other) {
if (other.comparator != comparator) {
throw new IllegalArgumentException("Can't combine with a summary statistics having a different comparator");
}
if (count == 0) {
min = other.min;
max = other.max;
} else if (other.count > 0) {
min = min(min, other.min);
max = max(max, other.max);
}
count += other.count;
}
public Optional<T> getMin() {
return Optional.ofNullable(min);
}
public Optional<T> getMax() {
return Optional.ofNullable(max);
}
public long getCount() {
return count;
}
private T min(T t1, T t2) {
return comparator.compare(t1, t2) <= 0 ? t1 : t2;
}
private T max(T t1, T t2) {
return comparator.compare(t1, t2) >= 0 ? t1 : t2;
}
}
然后你可以构造一个Collector 来收集到这个类:
public static <T> Collector<T, ?, ObjectSummaryStatistics<T>> summarizing(Comparator<T> comparator) {
return Collector.of(
() -> new ObjectSummaryStatistics<T>(comparator),
ObjectSummaryStatistics::accept,
(s1, s2) -> { s1.combine(s2); return s1; }
);
}
最后,你的代码变成:
ObjectSummaryStatistics<Person> s = detailedList.stream().collect(summarizing((d1, d2) -> d1.age() + d2.age()));
System.out.println(s.getMin());
System.out.println(s.getMax());
旁注:您的问题中的 Comparator 不是可传递的,因此它不会按原样工作