如何在 Java 8 中使用特定标准对列表列表进行分组

问题描述 投票:0回答:4

我有一个如下所示的数据结构。我试图以类似

Map<String, List<String>>
的方式对对象进行分组,其中键是entryId,值是它所属的组列表。 EntryId 在组内始终是唯一的。

示例:entryId“1111”属于group1、group2、group3。我正在使用旧的 java 7 方式来迭代列表并检查。有没有使用 Java8 收集器/分组来实现此目的的最佳方法。

List<Group>
其中每个 Group 对象都有一个 Entry 对象列表。

    [  
   {  
      "id":"group1",
      "entries":[  
         {  
            "entryId":"1111",
            "name":"test1"
         },
         {  
            "entryId":"2222",
            "name":"test2"
         },
         {  
            "entryId":"3333",
            "name":"test3"
         }
      ]
   },
   {  
      "id":"group2",
      "entries":[  
         {  
            "entryId":"4444",
            "name":"test1"
         },
         {  
            "entryId":"1111",
            "name":"test2"
         },
         {  
            "entryId":"2222",
            "name":"test3"
         }
      ]
   },
   {  
      "id":"group3",
      "entries":[  
         {  
            "entryId":"1111",
            "name":"test1"
         },
         {  
            "entryId":"5555",
            "name":"test2"
         },
         {  
            "entryId":"3333",
            "name":"test3"
         }
      ]
   }
]

所以预期的输出是这样的:

    [  
   {  
      "1111":[  
         "group1",
         "group2",
         "group3"
      ]
   },
   {  
      "2222":[  
         "group1",
         "group2"
      ]
   },
   {  
      "3333":[  
         "group1",
         "group3"
      ]
   },
   {  
      "4444":[  
         "group2"
      ]
   },
   {  
      "5555":[  
         "group3"
      ]
   }
]

我目前正在使用以下方式。它按预期工作,但是在 Java 8 中是否有更简单的方法可以实现这一点。

    public Map<String, List<String>> mapEntries(List<Group> groups) {
    Map<String, List<String>> entryMaps = new HashMap<>();
    for (Group group : groups) {
        for (Entry entry : group.getEntries()) {
            List<String> groupsEntryBelongs = new ArrayList<>();
            if (groups.iterator().hasNext() && !entryMaps.keySet().contains(entry.getEntryId())) {
                updateGroups(groups, entry.getEntryId(), groupsEntryBelongs, entryMaps);
            }
        }
    }
    return entryMaps;
}

    void updateGroups(List<Group> groups, String id, List<String> groupsEntryBelongs, Map<String, List<String>> entryMaps) {
        for (Group group : groups) {
            for (Entry entry : group.getEntries()) {
                if (entry.getEntryId().equalsIgnoreCase(id)) {
                    groupsEntryBelongs.add(group.getId());
                }
            }
        }
        entryMaps.put(id, groupsEntryBelongs);
    }
java java-8 java-stream grouping
4个回答
4
投票

您可以按照以下方式进行:

Map<String, Set<String>> entryMaps = new LinkedHashMap<>();
groups.forEach(group -> 
    group.getEntries().forEach(entry -> 
            entryMaps.computeIfAbsent(
                    entry.getEntryId().toLowerCase(),
                    k -> new LinkedHashSet<>())
                .add(group.getId())));

这将迭代组,然后迭代每个组的条目,并使用

Map.computeIfAbsent
放置一个带有新的空
LinkedHashSet
的条目(如果键不存在),返回此空集或与该键匹配的集。然后,将组 ID 添加到返回的集合中。

注意:我使用

Set
而不是
List
作为值,以避免可能的重复。并且
LinkedHashMap
LinkedhashSet
保证插入顺序。


1
投票

这样的东西应该可以工作,它需要制作某种中间元组对象:

groups.stream()
    .flatMap(group -> group.getEntries().stream()
            .map(entry -> Map.entry(entry.getEntryId(), group.getId())))
    .collect(Colectors.groupingBy(Map.Entry::getKey,
            Colectors.mapping(Map.Entry::getValue, toList())));

0
投票
List<List<EmployeeHourLogDetails>> resultLisSalesman = new ArrayList<> 
(employeeHourLogHeader.getEmployeeHourLogDetails().stream()
                        .collect(Collectors.groupingBy(d -> 
Arrays.asList(d.getEmployeeId(),
d.getName(),d.getAge()))).values());

-1
投票
List<List<EmployeeHourLogDetails>> resultLisSalesman = new ArrayList<> 
(employeeHourLogHeader.getEmployeeHourLogDetails().stream()
                        .collect(Collectors.groupingBy(d -> 
d.getEmployeeId())).values());
© www.soinside.com 2019 - 2024. All rights reserved.