【问题标题】:Transforming a Map in Java using Java 8 Streams - Segregating Map based on the Value of the Map使用 Java 8 Streams 在 Java 中转换地图 - 根据地图的值分离地图
【发布时间】:2020-04-16 21:01:10
【问题描述】:

我有一个 Java 地图:

Map<String, Set<EntityObject>> itemGroupsMap

class EntityObject {
  boolean isParent;
  String groupId;
}

现在我想将 itemGroupsMap 地图 --- 转换为 ---:

Map<EntityObject, Set<EntityObject>> parentChildMap.

要做的逻辑是itemGroupsMap -> Set -> 在这个Set中的每个条目都会有一个EntityObject,它将是一个父级(EntityObject.isParent=1)。因此,对于地图中的每个条目,我必须找到父 EntityObject 并将其设为 parentChildMap 的键,并将 仅其余的 entitiObjects 作为 Set/List键。

我尝试过使用 2 个 foreach 循环,而且我对 Java 8 还很陌生,所以正在研究如何使用流来减少我的代码?

我查看了 Collectors.partitioningBy,但它创建了 2 个具有 0、1 个键的映射。我真的不需要那个。

有什么建议吗?

【问题讨论】:

  • 我需要更多信息才能确定。您当前的地图包含多少个键(字符串部分)?一个或多个。结果映射将包含多少个键?一个或多个。
  • 您当前的地图包含多少个键(字符串部分)? - 许多
  • 生成的映射将包含多少个键? - 许多 -> 等于原始地图的数量 -> 每个条目都被转换为结果地图

标签: java object java-8 hashmap set


【解决方案1】:

可能是这样的:

Map<EntityObject, Set<EntityObject>> newMap = itemGroupsMap.entrySet().stream()
        .collect(Collectors.toMap(
                entry -> entry.getValue().stream().filter(value -> value.isParent).findFirst().orElse(null),
                Map.Entry::getValue
        ));

Note: 他的代码不关心没有父级的初始映射中的数据集 -> entry.getValue().stream().filter(value -&gt; value.isParent).findFirst().orElse(null), 它告诉:当集合中没有父级时,将null 设置为键。因此,如果有可能,那么没有父级的每个集合都将被下一个没有父级的集合覆盖。

【讨论】:

  • 我不希望在结果映射中没有父母的条目。
【解决方案2】:

这里有几种方法,假设我了解您想要什么。如果 map 的键是 EntityObject,那么它需要覆盖 equals 以处理不允许的重复键。这可以通过使用 Id 作为 equals 实现的一部分来完成(这在提供的类中并不明显)

            Map<EntityObject, Set<EntityObject>> parentChildMap =
                itemGroupsMap.entrySet().stream()
                        .collect(Collectors.toMap(
                                // get the single parent object and use
                                // as a key
                                e -> e.getValue().stream()
                                        .filter(o -> o.isParent)
                                        .findFirst().get(),
                                // get the value and remove the parent
                                // key, convert to a set and use as the new
                                // value.
                                e -> e.getValue().stream()
                                        .filter(o -> !o.isParent)
                                        .collect(
                                                Collectors.toSet())));

可能有更好的方法来处理流,但我更喜欢以下方法,因为它是直截了当的。

        // create the map
        Map<EntityObject, Set<EntityObject>> parentChildMap = new HashMap<>();

        for (Entry<String, Set<EntityObject>> e : itemGroupsMap
                .entrySet()) {

            // get the set of EntityObjects
            Set<EntityObject> eoSet = e.getValue();

            // get the parent one
            EntityObject parentObject = eoSet.stream()
                    .filter(eo->eo.isParent).findFirst().get();

            // remove the parent one from the set
            eoSet.remove(parentObject);

            // add the parentObject and the set to the map
            parentChildMap.put(parentObject,eoSet);
        }

【讨论】:

    猜你喜欢
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-07
    • 1970-01-01
    • 2021-04-12
    • 2012-11-30
    • 1970-01-01
    相关资源
    最近更新 更多