Java Streams:将集合组织到地图中并选择最小的键

时间:2016-03-19 23:08:42

标签: java java-8 java-stream

我很确定这行不可能,但我只想查一下:

List<WidgetItem> selectedItems = null;
Map<Integer, List<WidgetItem>> itemsByStockAvailable = WidgetItems.stream()
     .collect(Collectors.groupingBy(WidgetItem::getAvailableStock));
selectedItems = itemsByStockAvailable.get(
     itemsByStockAvailable.keySet().stream().sorted().findFirst().get());

基本上我将所有小部件项目收集到地图中,其中关键字是可用的库存数量,值是具有该数量的所有小部件的列表(因为多个小部件可能具有相同的值)。一旦我有了这张地图,我就想选择与最小键对应的地图值。创建地图的中间步骤是不必要的,这是我能想到的唯一方法。

5 个答案:

答案 0 :(得分:6)

您希望保留所有以最低可用库存分组的窗口小部件项目。在这种情况下,您可以将分组数据收集到TreeMap中,以确保根据库存值的增加进行排序,并使用firstEntry()检索第一个条目

List<WidgetItem> selectedItems = 
    widgetItems.stream()
               .collect(Collectors.groupingBy(
                  WidgetItem::getAvailableStock,
                  TreeMap::new,
                  Collectors.toList()
               ))
               .firstEntry()
               .getValue();

优点是它完成了初始列表的一次传递。

答案 1 :(得分:2)

基本上,您希望根据自定义比较器Comparator.comparingInt(WidgetItem::getAvailableStock)获取最小的所有输入元素。通常,这个问题可以解决而无需将所有内容存储到中间映射中,从而产生不必要的垃圾。它也可以单程解决。 this问题中已经存在一些有趣的解决方案。例如,您可以使用Stuart Marks实现的收集器:

List<WidgetItem> selectedItems = widgetItems.stream()
           .collect(maxList(
               Comparator.comparingInt(WidgetItem::getAvailableStock).reversed()));

我的StreamEx图书馆随时可以使用这些收藏家。最适合您的情况是MoreCollectors.minAll(Comparator)

List<WidgetItem> selectedItems = widgetItems.stream()
           .collect(MoreCollectors.minAll(
               Comparator.comparingInt(WidgetItem::getAvailableStock)));

答案 2 :(得分:1)

您可以在第一遍中找到最小的密钥,然后获取具有该最小密钥的所有项目:

widgetItems.stream()
           .map(WidgetItem::getAvailableStock)
           .min(Comparator.naturalOrder())
           .map(min -> 
               widgetItems.stream()
                          .filter(item -> item.getAvailableStock().equals(min))
                          .collect(toList()))
           .orElse(Collections.emptyList());

答案 3 :(得分:1)

如果您想避免创建中间地图,您可以先确定最小的库存值,按该值过滤并收集到列表。

int minStock = widgetItems.stream()
    .mapToInt(WidgetItem::getAvailableStock)
    .min()
    .getAsInt();  // or throw if list is empty

List<WidgetItem> selectItems = widgetItems.stream()
    .filter(w -> minStock == w.getAvailableStock())
    .collect(toList());

另外,请勿使用sorted().findFirst()来查找流的最小值。请改用min

答案 4 :(得分:0)

我会将数据收集到NavigableMap中,只需对原始代码进行一些小改动:

List<WidgetItem> selectedItems = null;
NavigableMap<Integer, List<WidgetItem>> itemsByStockAvailable =
    WidgetItems.stream()
        .collect(Collectors.groupingBy(WidgetItem::getAvailableStock,
            TreeMap::new, Collectors.toList()));
selectedItems = itemsByStockAvailable.firstEntry().getValue();