简体   繁体   English

Java 8 如何通过枚举类型合并多个列表

[英]Java 8 how to merge multiple lists by enum type

How to merge multiple lists in Java 8 by enum type?如何通过枚举类型合并 Java 8 中的多个列表?

I have 2 lists:我有 2 个列表:

List<StatusSummary> listA //4 items because we have 4 enum types
List<StatusSummary> listB //4 items because we have 4 enum types

class StatusSummary {
  private StatusEnum resourcesStatus; //4 statuses: TypeA, TypeB, TypeC, TypeD
  private Integer count;
}

I want to have one list consisting of 4 items for each resourcesStatus: TypeA, TypeB, TypeC, TypeD with the sum of elements in count field like:我想要一个包含每个resourcesStatus: TypeA, TypeB, TypeC, TypeD以及count字段中的元素总和,例如:

List<StatusSummary> listA+B with 4 objects:
(resourcesStatus: TypeA, count: 3), (resourcesStatus: TypeB, count:99), (resourcesStatus: typeC, count:322), (resourcesStatus: TypeD, count:2)

So far I implemented something like this:到目前为止,我实现了这样的事情:

listA
    .getResourcesStatus()
    .forEach(la -> listB.getResourcesStatus().stream()
        .filter(lb -> lb.getResourcesStatus() == la.getResourcesStatus())
        .forEach(lb -> result.add(new StatusSummary()
            .count(la.getCount() + lb.getCount())
        .status(la.getStatus()))));

You can use Collectors.toMap .您可以使用Collectors.toMap Map by ResourcesStatus and merge two StatusSummary with count field in merge-function for the same ResourcesStatus then you get Map<StatusEnum, StatusSummary> and then get values of the map using .values() in ArrayList . Map 通过ResourcesStatus并将两个StatusSummary与合并函数中的count字段合并为相同的ResourcesStatus然后你得到Map<StatusEnum, StatusSummary>然后使用.values()的值获取 map 的值在ArrayList

List<StatusSummary> newList = 
           new ArrayList<>(
                  Stream.of(listA, listB)
                 .flatMap(Collection::stream)
                 .collect(Collectors.toMap(e -> e.getResourcesStatus(), i -> i,
                   (a,b) -> new StatusSummary(a.getResourcesStatus(),
                                                a.getCount() + b.getCount())))
                 .values());

Problem using forEach使用forEach的问题

As far as I see your current solution using forEach , you approach to Stream API as it would be a simple for-loop with additional features.据我看到您当前使用forEach的解决方案,您接近 Stream API 因为这将是一个具有附加功能的简单 for 循环。 You violate the Side-effects principle of which in a nutshell says that a stream shouldn't modify another collection while performing the actions through the pipelines.您违反了 的副作用原则,简而言之,stream 在通过管道执行操作时不应修改另一个集合。 I haven't tested your code, however, this is not a way you should treat streams.我没有测试你的代码,但是,这不是你应该处理流的方式。

One of the possible solutions可能的解决方案之一

You can use Collectors.groupingBy with Collectors.summingInt to get Map<StatusEnum, Integer> with the status and a sum of counts.您可以使用Collectors.groupingByCollectors.summingInt来获取Map<StatusEnum, Integer>的状态和计数总和。 Each entry then can be transformed into StatusSummary and colleted as List :然后可以将每个条目转换为StatusSummary并作为List收集:

 List<StatusSummary> list = Stream.of(listA, listB)
     .flatMap(List::stream)
     .collect(Collectors.groupingBy(                        // Map<StatusSummary, Integer>
          StatusSummary::getResourcesStatus,                // .. StatusEnum as key
          Collectors.summingInt(StatusSummary::getCount)))  // .. Integer as value (sum)
     .entrySet()
     .stream()                                              // Stream<Entry<..>>
     .map(e -> new StatusSummary(e.getKey(), e.getValue())) // Stream<StatusSummary>
     .collect(Collectors.toList());                         // List<StatusSummary>

... or using Collectors.collectingAndThen (not less verbose): ...或使用Collectors.collectingAndThen (不那么冗长):

List<StatusSummary> list1 = Stream.of(listA, listB, listC)
    .flatMap(List::stream)
    .collect(Collectors.collectingAndThen(
         Collectors.groupingBy(
             StatusSummary::getResourcesStatus, 
             Collectors.summingInt(StatusSummary::getCount)),
         map -> map.entrySet().stream()
             .map(e -> new StatusSummary(e.getKey(), e.getValue()))
             .collect(Collectors.toList())));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM