使用forEach,Java 8创建List列表(嵌套列表)

che*_*cho 7 java nested-lists java-8 java-stream

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<>();
Run Code Online (Sandbox Code Playgroud)

现在使用流我想填写如下:

 1 -> {"secondBirdOne", "secondBirdTwo", "secondBirdThree"}
 2 -> {"secondCatOne", "secondCatTwo", "secondCatThree"}
 3 -> {"secondDogOne", "secondDogTwo", "secondDogThree"}
Run Code Online (Sandbox Code Playgroud)

我的UNFINISHED(那是问题)代码是:

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

Era*_*ran 10

collect是用于生成输出更合适的终端操作MapforEach.

你可以用collect()Collectors.groupingBy:

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

Collectors.groupingBy用一个参数(只是e -> e.getId().getFirstId())会产生一个Map<Long,List<EntityComposite>>.

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


Ous*_* D. 9

有几种不同的方法可以完成手头的任务.

forEach + computeIfAbsent

 Map<Long, List<String>> map = new HashMap<>();
 listEntityComposite.forEach(e -> map.computeIfAbsent(e.getId().getFirstId(), 
                k -> new ArrayList<>()).add(e.getSecond()));
Run Code Online (Sandbox Code Playgroud)
  • 枚举listEntityCompositevia中的元素forEach
  • 每个元素computeIfAbsent用于计算密钥(即firstId)和值(即List<String>)

groupingBy + mapping

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

Map<Long, List<String>> resultSet = listEntityComposite.stream()
                .collect(groupingBy(e -> e.getId().getFirstId(),
                        mapping(EntityComposite::getSecond, toList())));
Run Code Online (Sandbox Code Playgroud)
  • 通过分类函数对源元素进行分组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;}));
Run Code Online (Sandbox Code Playgroud)
  • 枚举listEntityCompositevia中的元素forEach

  • 每个元素merge用于计算密钥(即firstId)和值(即List<String>)

toMap

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

总而言之,forEach+ computeIfAbsent方法和groupingBy+ mapping方法是你在这个特定情况下应该支持的两种方法,因为它们更具惯用性.