【问题标题】:stream creating List of List (nested List) using forEach, Java 8使用 forEach,Java 8 创建列表列表(嵌套列表)的流
【发布时间】:2018-12-14 20:11:35
【问题描述】:
class EntityCompositeId {
    private Long firstId;
    private Long secondId;
    // getter & setter...
}

class EntityComposite {
    private EntityCompositeId id;
    private String first;
    private String second;
    // getter & setter...
}

List<EntityComposite> listEntityComposite = ....
Supose this content

1, 1, "firstA", "secondBirdOne"
1, 2, "firstA", "secondBirdTwo"
1, 3, "firstA", "secondBirdThree"

2, 1, "firstB", "secondCatOne"
2, 2, "firstB", "secondCatTwo"
2, 3, "firstB", "secondCatThree"

3, 1, "firstC", "secondDogOne"
3, 2, "firstC", "secondDogTwo"
3, 3, "firstC", "secondDogThree"

Map<Long, List<String>> listOfLists = new HashMap<>();

现在使用我想填充的流:

 1 -> {"secondBirdOne", "secondBirdTwo", "secondBirdThree"}
 2 -> {"secondCatOne", "secondCatTwo", "secondCatThree"}
 3 -> {"secondDogOne", "secondDogTwo", "secondDogThree"}

我的未完成(这就是问题)代码是:

listEntityComposite.stream()forEach(entityComposite {
        // How create a list according entityComposite.getId.getFirstId()?
        listOfLists.put(entityComposite.getId.getFirstId(), .... )
    });

【问题讨论】:

    标签: java java-8 java-stream nested-lists


    【解决方案1】:

    collect 是比forEach 更适合生成输出Map 的终端操作。

    您可以将collect()Collectors.groupingBy 一起使用:

    Map<Long, List<String>> listOfLists =
        listEntityComposite.stream()
                           .collect(Collectors.groupingBy(e -> e.getId().getFirstId(),
                                                          Collectors.mapping(EntityComposite::getSecond,
                                                                             Collectors.toList());
    

    Collectors.groupingBy 带有一个参数(只是e -&gt; e.getId().getFirstId())会生成一个Map&lt;Long,List&lt;EntityComposite&gt;&gt;

    链接到它Collectors.mapping() 将每个EntityComposite 实例映射到相应的getSecond() String,根据需要。

    【讨论】:

    【解决方案2】:

    您可以通过多种不同的方法来完成手头的任务。

    forEach + computeIfAbsent

     Map<Long, List<String>> map = new HashMap<>();
     listEntityComposite.forEach(e -> map.computeIfAbsent(e.getId().getFirstId(), 
                    k -> new ArrayList<>()).add(e.getSecond()));
    
    • 通过forEach 枚举listEntityComposite 中的元素
    • 对于每个元素,使用computeIfAbsent 计算键(即firstId)和值(即List&lt;String&gt;

    groupingBy + mapping

    另一种方法是应用groupingBymapping 下游收集器:

    Map<Long, List<String>> resultSet = listEntityComposite.stream()
                    .collect(groupingBy(e -> e.getId().getFirstId(),
                            mapping(EntityComposite::getSecond, toList())));
    
    • 通过分类函数e.getId().getFirstId() 对源元素进行分组,然后应用mapping 下游收集器进一步细化我们的查询。

    forEach + merge

    listEntityComposite.forEach(e -> map.merge(e.getId().getFirstId(),
                    new ArrayList<>(singletonList(e.getSecond())),
                    (l, r) -> {l.addAll(r); return l;}));
    
    • 通过forEach枚举listEntityComposite中的元素

    • 对于每个元素,使用merge 来计算键(即firstId)和值(即List&lt;String&gt;

    toMap

    listEntityComposite.stream()
                       .collect(toMap(e -> e.getId().getFirstId(), 
                                 v ->  new ArrayList<>(singletonList(v.getSecond())),
                                 (l, r) -> {l.addAll(r); return l;}));
    
    • 应用keyMapper 函数e -&gt; e.getId().getFirstId() 来提取地图键。
    • 应用valueMapper 函数v -&gt; new ArrayList&lt;&gt;(singletonList(v.getSecond())) 来提取地图值。
    • 应用merge 函数(l, r) -&gt; {l.addAll(r); return l;} 来解决键冲突。

    总之,forEach + computeIfAbsent 方法和 groupingBy + mapping 方法是在这种特定情况下您应该支持的两种方法,因为它们更符合习惯。

    【讨论】:

      【解决方案3】:

      我建议研究一下 Guava 的 MultiMap,它可以让您的用例更易于处理(提供大量优化和您以后可能想要获得的额外功能)

      编辑: 为什么 Multimap 比使用 computeIfAbsent 方法更有意义的一个例子: 1.每个键都有一个一定大小的列表,如果你以后想得到“总”大小怎么办?您必须创建一些逻辑才能以良好的性能实现这一点(或使用采用 O(keys) 的方法) 2. 目前你只是在地图上放东西,但是如果你以后想从地图上移除东西怎么办?您将需要编写一些样板代码(很容易出错)以确保删除值不会导致内存泄漏

      使用多图还有其他好处,但这只是两个容易解释的好处。

      编辑 2: 使用您的输入的示例:

      import java.util.Arrays;
      import java.util.List;
      
      import com.google.common.collect.ArrayListMultimap;
      import com.google.common.collect.ListMultimap;
      
      public class Example {
      
          public static class EntityCompositeId {
              @Override
              public String toString() {
                  return "EntityCompositeId [firstId=" + firstId + ", secondId=" + secondId + "]";
              }
      
              public EntityCompositeId(Long firstId, Long secondId) {
                  super();
                  this.firstId = firstId;
                  this.secondId = secondId;
              }
      
              private Long firstId;
      
              public Long getFirstId() {
                  return firstId;
              }
      
              private Long secondId;
          }
      
          public static class EntityComposite {
              @Override
              public String toString() {
                  return "EntityComposite [id=" + id + ", first=" + first + ", second=" + second + "]";
              }
      
              public EntityComposite(EntityCompositeId id, String first, String second) {
                  super();
                  this.id = id;
                  this.first = first;
                  this.second = second;
              }
      
              private EntityCompositeId id;
      
              public EntityCompositeId getId() {
                  return id;
              }
      
              private String first;
              private String second;
          }
      
          public static void main(String[] args) {
              List<EntityComposite> listEntityComposite = Arrays.asList(
                      new EntityComposite(new EntityCompositeId(1l, 1l), "firstA", "secondBirdOne"),
                      new EntityComposite(new EntityCompositeId(1l, 2l), "firstA", "secondBirdTwo"),
                      new EntityComposite(new EntityCompositeId(1l, 3l), "firstA", "secondBirdThree"),
                      new EntityComposite(new EntityCompositeId(2l, 1l), "firstB", "secondCatOne"),
                      new EntityComposite(new EntityCompositeId(2l, 2l), "firstB", "secondCatTwo"),
                      new EntityComposite(new EntityCompositeId(2l, 3l), "firstB", "secondCatThree"),
                      new EntityComposite(new EntityCompositeId(3l, 1l), "firstC", "secondDogOne"),
                      new EntityComposite(new EntityCompositeId(3l, 2l), "firstC", "secondDogTwo"),
                      new EntityComposite(new EntityCompositeId(3l, 3l), "firstC", "secondDogThree"));
              ListMultimap<Long, EntityComposite> map = ArrayListMultimap.create();
              listEntityComposite.forEach(entityComposite -> map.put(entityComposite.getId().getFirstId(), entityComposite));
              map.keySet().forEach(key -> System.out.println(map.get(key)));
          }
      }
      

      产生以下输出:

      [EntityComposite [id=EntityCompositeId [firstId=1, secondId=1], first=firstA, second=secondBirdOne], EntityComposite [id=EntityCompositeId [firstId=1, secondId=2], first=firstA, second=secondBirdTwo], EntityComposite [id=EntityCompositeId [firstId=1, secondId=3], first=firstA, second=secondBirdThree]]
      [EntityComposite [id=EntityCompositeId [firstId=2, secondId=1], first=firstB, second=secondCatOne], EntityComposite [id=EntityCompositeId [firstId=2, secondId=2], first=firstB, second=secondCatTwo], EntityComposite [id=EntityCompositeId [firstId=2, secondId=3], first=firstB, second=secondCatThree]]
      [EntityComposite [id=EntityCompositeId [firstId=3, secondId=1], first=firstC, second=secondDogOne], EntityComposite [id=EntityCompositeId [firstId=3, secondId=2], first=firstC, second=secondDogTwo], EntityComposite [id=EntityCompositeId [firstId=3, secondId=3], first=firstC, second=secondDogThree]]
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-02-17
        • 2018-07-14
        • 2016-07-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多