按属性查找最小值,以列表形式返回

时间:2016-04-12 15:15:17

标签: java lambda java-8 java-stream

我有一个类似的课程:

public class Product{
    public Integer category;
    public Integer price;    

    // getters and setters omitted
}

有了不同类别和价格的产品清单,我想返回一个包含每个类别最便宜产品的清单。我已经找到了一种方法来将此作为一个以类别为键的地图,但我想要一个列表。什么是简洁易读的方法呢?

这是我到目前为止给我的地图:

Map<String, Product> cheapestProducts = products.stream()
   .collect(
       groupingBy(                                                      
           Product::getCategory,
               collectingAndThen(minBy(comparing(Product::getPrice)), p -> p.get())
       )
   );

3 个答案:

答案 0 :(得分:2)

您可以使用toMap方法,然后调用map.values():

Collection<Product> cheapestProducts = products
            .stream()
            .collect(Collectors.toMap(t -> t.category, u -> u,
                    (a, b) -> a.price > b.price ? b : a))
            .values();

如果您真的想要一份清单,请参阅上面的Holger评论。

答案 1 :(得分:1)

在我看来,你的方法还可以。问题在于可读性,我认为解决方案是在需要时提取方法使其可重复使用。 Java 8流是流畅的,等等,但通常有诱惑,使流20行,这会损害可读性。因此,通过提取方法getMinBy()(可能有一个更好的名称),它封装了minByOptional::get,我认为它更具可读性。当然,该方法本身并不简洁,但可以重复使用。

    Map<Integer, Product> cheapestProducts = products.stream()
            .collect(
                    groupingBy(
                            Product::getCategory,
                            getMinBy(Product::getPrice)
                    ));


    private static <T,C extends Comparable<? super C>> Collector<T, ?, T> getMinBy(Function<T, C> comparatorFunction) {
        return collectingAndThen(minBy(comparing(comparatorFunction)), Optional::get);
    }

答案 2 :(得分:0)

要从Map获取值到列表,您可以执行以下操作...

List<Value> list = new ArrayList<Value>(map.values());