【问题标题】:List stream, get items with lowest price [duplicate]列出流,以最低价格获取商品[重复]
【发布时间】:2016-10-18 16:14:09
【问题描述】:

我有一个List<Hotel>,每个Hotel都有一个BigDecimal minSellingPrice,我想以最低售价获得Hotel。

我可以通过这段代码实现这一点

hotels.stream().min((h1, h2) -> h1.getMinSellingPrice().compareTo(h2.getMinSellingPrice())).get()

但是如果列表中的 3 家酒店有共同的最低售价,那么列表中有 50 家酒店,最低的 minSellingPrice 是 100,50 家酒店中有 3 家酒店的 minSellingPrice 是 100。

我如何获得这 3 家酒店的列表,以便对它们进行操作?我唯一想到的是通过map 和min 获得最低价格,然后在列表中查询价格最低的商品,但这听起来不太好。

【问题讨论】:

标签: java java-stream


【解决方案1】:

您可以在下面尝试获得最小酒店

Hotel min = hotels.stream().min(Comparator.comparing(Hotel::getSellingPrice)).orElse(null);

为了获得多个酒店,您需要使用 groupingBy

Map<BigDecimal, List<Hotel>> groupedHoted = hotels.stream().collect(Collectors.groupingBy(Hotel::getSellingPrice, TreeMap::new, Collectors.toList()));

更新

根据 cmets 编辑

groupedHoted = new TreeMap<>(hotels.stream().collect(Collectors.groupingBy(Hotel::getSellingPrice)));

使用reduce(不推荐)

    Map<BigDecimal, List<Hotel>> sorted = hotels.stream().reduce(new TreeMap<BigDecimal, List<Hotel>>(), (map, hotel) -> {
        if (map.get(hotel.getSellingPrice()) == null) {
            map.put(hotel.getSellingPrice(), new ArrayList<>());
        }
        map.get(hotel.getSellingPrice()).add(hotel);
        return map;
    }, (map1, map2) -> {
        map1.putAll(map2);
        return map1;
    });

输出

{10=[Hotel [sellingPrice=10], Hotel [sellingPrice=10]], 20=[Hotel [sellingPrice=20], Hotel [sellingPrice=20]], 30=[Hotel [sellingPrice=30]]}

【讨论】:

  • @erickson 我没有抄袭你,我已经在 SO 中回答了类似的问题,我错误地理解了这个问题,然后我更正了我的答案
  • @erickson 编辑了我的答案,它排序的地图,用户可以迭代并获得他们想要的酒店数量
  • 谢谢。顺便说一句,您的第二个代码块和第三个代码块没有区别。我很难接受答案,所以我接受了之前发布的答案。不过赞赏:)
【解决方案2】:

使用Collectors.groupingBy() 的形式,允许您指定要使用的Map 的类型,并指定SortedMap 或NavigableMap 实现。然后,您可以轻松地从结果中检索最小元素的集合。

NavigableMap<BigDecimal, List<Hotel>> hotelByPrice = hotels.stream()
    .collect(Collectors.groupingBy(Hotel::getMinSellingPrice, TreeMap::new, Collectors.toList()));
List<Hotel> cheapest = hotelByPrice.firstEntry().getValue();

【讨论】:

    【解决方案3】:

    如果要对酒店列表进行排序:

    Comparator<Hotel> comp = new Comparator<Hotel>() {
                public int compare(Hotel o1, Hotel o2) {
                    return o1.getMinSellingPrice() - o2.getMinSellingPrice();
                }
            };
    
    hotels = hotels.stream().sorted(comp).collect(Collectors.toList());
    

    这使用了一个比较器,documentation here。

    或者返回列表中的最低售价:

    hotels.stream().map(i -> i.getMinSellingPrice()).min(Comparator.naturalOrder()).get());
    

    这只是将酒店列表映射到他们的 minSellingPrice 列表,然后取最小值。

    【讨论】:

    • 谢谢,我可能需要尽快整理一些结果。
    【解决方案4】:

    另一种可能性。

    List<Hotel> minHotels = hotels.stream()
        .filter(h -> h.minSellingPrice == hotels.stream()
            .map(Hotel::getMinSellingPrice).sorted().findFirst().orElse(null))
        .collect(Collectors.toList());
    

    【讨论】:

      猜你喜欢
      • 2015-01-31
      • 2022-11-17
      • 2015-11-05
      • 1970-01-01
      • 2021-05-03
      • 2011-10-03
      • 1970-01-01
      • 1970-01-01
      • 2016-05-09
      相关资源
      最近更新 更多