小编典典
如果您只对Car每个组感兴趣,则可以使用,例如
Map mostExpensives = carsDetails.stream()
.collect(Collectors.toMap(Car::getMake, Function.identity(),
BinaryOperator.maxBy(Comparator.comparing(Car::getPrice))));
mostExpensives.forEach((make,car) -> System.out.println(make+" "+car));
但是,由于您想要最昂贵和最便宜的产品,因此需要以下内容:
Map> mostExpensivesAndCheapest = carsDetails.stream()
.collect(Collectors.toMap(Car::getMake, car -> Arrays.asList(car, car),
(l1,l2) -> Arrays.asList(
(l1.get(0).getPrice()>l2.get(0).getPrice()? l2: l1).get(0),
(l1.get(1).getPrice()
mostExpensivesAndCheapest.forEach((make,cars) -> System.out.println(make
+" cheapest: "+cars.get(0)+" most expensive: "+cars.get(1)));
由于没有与之等效的通用统计对象,因此该解决方案带来了一些不便DoubleSummaryStatistics。如果这种情况不止一次发生,那么值得用这样的类填补空白:
/**
* Like {@code DoubleSummaryStatistics}, {@code IntSummaryStatistics}, and
* {@code LongSummaryStatistics}, but for an arbitrary type {@code T}.
*/
public class SummaryStatistics implements Consumer {
/**
* Collect to a {@code SummaryStatistics} for natural order.
*/
public static > Collector>
statistics() {
return statistics(Comparator.naturalOrder());
}
/**
* Collect to a {@code SummaryStatistics} using the specified comparator.
*/
public static Collector>
statistics(Comparator comparator) {
Objects.requireNonNull(comparator);
return Collector.of(() -> new SummaryStatistics<>(comparator),
SummaryStatistics::accept, SummaryStatistics::merge);
}
private final Comparator c;
private T min, max;
private long count;
public SummaryStatistics(Comparator comparator) {
c = Objects.requireNonNull(comparator);
}
public void accept(T t) {
if(count == 0) {
count = 1;
min = t;
max = t;
}
else {
if(c.compare(min, t) > 0) min = t;
if(c.compare(max, t) < 0) max = t;
count++;
}
}
public SummaryStatistics merge(SummaryStatistics s) {
if(s.count > 0) {
if(count == 0) {
count = s.count;
min = s.min;
max = s.max;
}
else {
if(c.compare(min, s.min) > 0) min = s.min;
if(c.compare(max, s.max) < 0) max = s.max;
count += s.count;
}
}
return this;
}
public long getCount() {
return count;
}
public T getMin() {
return min;
}
public T getMax() {
return max;
}
@Override
public String toString() {
return count == 0? "empty": (count+" elements between "+min+" and "+max);
}
}
将其添加到您的代码库后,您可以像
Map> mostExpensives = carsDetails.stream()
.collect(Collectors.groupingBy(Car::getMake,
SummaryStatistics.statistics(Comparator.comparing(Car::getPrice))));
mostExpensives.forEach((make,cars) -> System.out.println(make+": "+cars));
如果getPrice回报double,也可能是使用更有效Comparator.comparingDouble(Car::getPrice)的替代Comparator.comparing(Car::getPrice)。
2020-09-26