【问题标题】:How to group List of Lists using a certain criteria in Java 8如何在 Java 8 中使用特定标准对列表进行分组
【发布时间】:2019-04-14 18:09:32
【问题描述】:

我有一个如下所示的数据结构。我正在尝试以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);
    }

【问题讨论】:

  • 我使用这种方式遍历组并获取第一个条目 id,然后检查剩余的组以更新我创建的对象 Map>。我得到了我需要的结果,但要求在 java8 中实现它的建议。
  • 始终值得分享您在问题中所做的尝试,以明确您的预期输出。
  • @uli 不,这不是我要找的。我用预期的输出和我目前的做法更新了我的问题。你指的那个不一样。我正在尝试按内部列表中的值进行分组。

标签: java java-8 java-stream grouping


【解决方案1】:

你可以这样做:

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 作为值,以避免可能的重复。并且LinkedHashMapLinkedhashSet 保证插入顺序。

【讨论】:

  • 谢谢。有效。根据您的实现,我必须这样声明。 Map> entryMaps = new LinkedHashMap()
【解决方案2】:

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

list.stream()
.flatMap(group ->
   group.getEntries.stream()
        .map(entry -> new GroupEntry(group.getId(), entry.getEntryId()))
)
.collect(
   Collectors.groupingBy(GroupEntry::getEntryId, Collectors.mapping(GroupEntry::getGroupId, Collectors.toList())));

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-30
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 2017-07-20
    • 2018-11-18
    • 2017-05-06
    相关资源
    最近更新 更多