【问题标题】:Appending to a list within a stream to a map将流中的列表附加到地图
【发布时间】:2019-09-01 14:51:51
【问题描述】:

我正在尝试将多个不必要的 Web 请求合并到一张地图中,其中键连接到位置的 ID,值是该位置的产品列表。

这个想法是通过为每个位置创建一个请求并映射到它的所需产品列表来减少对我的烧瓶服务器的请求量。

我曾尝试使用 Java 8 的流式传输功能找到遇到类似问题的其他人,但我找不到任何尝试追加到地图中的列表的人。

示例;

public class Product {
    public Integer productNumber();
    public Integer locationNumber();
}

List<Product> products = ... (imagine many products in this list)

Map<Integer, List<Integer>> results = products.stream()
    .collect(Collectors.toMap(p -> p.locationNumber, p -> Arrays.asList(p.productNumber));

另外,第二个p 参数无法访问流中的当前产品。

因此,当位置编号与预先存在的列表匹配时,我无法测试是否可以附加到列表中。我不相信我可以使用 Arrays.asList(),因为我相信它是不可变的。

最后,地图应该在每个位置的列表中包含许多产品编号。是否可以将整数附加到地图中的预先存在的列表中?

【问题讨论】:

  • Collectors.toMap(p -&gt; p.locationNumber, p -&gt; Arrays.asList(p.productNumber), (l1,l2) -&gt; {l1.addAll(l2);return l1;}) 也可以为您工作。虽然grouping 在这里更有意义。

标签: java list dictionary java-stream


【解决方案1】:

你可以这样做,

Map<Integer, List<Integer>> res = products.stream()
    .collect(Collectors.groupingBy(Product::locationNumber,
        Collectors.mapping(Product::productNumber, Collectors.toList())));

【讨论】:

    【解决方案2】:

    Java 收集器 API 非常强大,并且有很多很好的实用方法来解决这个问题。

    
    public class Learn {
    
        static class Product {
            final Integer productNumber;
            final Integer locationNumber;
    
            Product(Integer productNumber, Integer locationNumber) {
                this.productNumber = productNumber;
                this.locationNumber = locationNumber;
            }
    
            Integer getProductNumber() {
                return productNumber;
            }
    
            Integer getLocationNumber() {
                return locationNumber;
            }
        }
    
        public static Product of(int i, int j){
            return new Product(i,j);
        }
    
        public static void main(String[] args) {
    
    
            List productList = Arrays.asList(of(1,1),of(2,1),of(3,1),
                    of(7,2),of(8,2),of(9,2));
    
            Map> results = productList.stream().collect(Collectors.groupingBy(Product::getLocationNumber,
                    Collectors.collectingAndThen(Collectors.toList(), pl->pl.stream().map(Product::getProductNumber).collect(Collectors.toList()))));
    
            System.out.println(results);
        }
    }
    

    因此,我们在这里所做的是流式传输产品列表并按位置属性对流进行分组,但我们希望将收集的产品列表转换为产品编号列表。

    Collectors.collectingAndThen 正是这种方法,它可以让你指定一个主收集器 toList() 和一个转换器函数,它只是一个将产品映射到产品编号的流。在 java API doc 中,主收集器和转换器被标记为下游收集器和完成器。

    请仔细阅读收集器源代码,以全面了解所有这些不同收集器的定义方式。

    【讨论】:

      猜你喜欢
      • 2021-11-14
      • 1970-01-01
      • 2013-07-06
      • 1970-01-01
      • 1970-01-01
      • 2020-01-12
      • 2015-10-01
      • 1970-01-01
      相关资源
      最近更新 更多