使用 Java Streams API 比较两个 HashMap 并替换一个 HashMap 中的属性值

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

我有 2 个哈希图

HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap 

HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap 

 DedupeTableEntity 有 id、国家/地区、entity_flag 作为属性

  • 我想迭代 delta 哈希映射的值(两个哈希映射 只有 1 个键和该键下的值列表)

  • 如果有 2 个属性,则检查该对象是否在现有哈希映射中 匹配(国家/地区和 ID)

  • 如果存在

  • 从中获取该对象(实体标志)的属性值 并替换现有的hashmap的属性(实体标志)值 Delta 哈希图中的相同对象

    public void compareTwoHashmaps(HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap 
    , HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap){
            //iterate through deltahashmap values
            return deltaHashmap.values().stream()
                    .flatMap(Collection::stream)
                    .filter(c -> (existingHashmap.values().stream().flatMap(Collection::stream).filter(e->e.getId().equals(c.getId()) && e.getObjectCountry().equals(c.getObjectCountry())))
                            .map(k-> k.setEntityFlag(existingHashmap.values().stream().flatMap(Collection::stream).filter(e->e.getId().equals(k.getId()) && e.getObjectCountry().equals(k.getObjectCountry())).map(r ->r.getEntityFlag()).toString()));
        }
    

这就是我到目前为止所得到的。但有一个错误我不知道如何纠正

如有任何帮助,我们将不胜感激

java dictionary hashmap java-stream
3个回答
1
投票
  • 通过
    existingHashmap
    deltaHashmap
    中的每个元素执行线性扫描是极其浪费的。
  • map
    不适用于对流中的每个元素执行操作
    map
    用于更改 Stream 中返回的元素。要执行操作,您应该使用 forEach
  • 在 Stream 上调用 toString() 不太可能产生有用的信息。

我首先会通过用于匹配的属性来映射

existingHashMap
的值。实现复合键的一种简单方法是定义一个 record 类。这种通过可匹配属性进行的映射允许更快地搜索匹配项,而无需针对 deltaHashmap 中的每个值检查现有Hashmap 的每个值。 (记录类根据其成员自动定义 equals、hashCode 和 toString 方法。)

此处不应使用

map
,因为它返回一个值,但没有可返回的值。您正在实体中设置属性。这样做不会返回任何内容。

public void compareTwoHashmaps(
    HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap,
    HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap) {

    record Identifiers(String id, String country) {
        static Identifiers of(DedupeTableEntity entity) {
            return new Identifiers(entity.getId(),
                                   entity.getObjectCountry());
        }
    }

    Map<Identifiers, DedupeTableEntity> allExisting =
        existingHashmap.values().stream().flatMap(Collection::stream)
            .collect(Collectors.toMap(Identifiers::of, e -> e));

    deltaHashmap.values().stream().flatMap(Collection::stream)
        .forEach(delta -> {
            DedupeTableEntity existing =
                allExisting.get(Identifiers.of(delta));

            if (existing != null) {
                delta.setEntityFlag(existing.getEntityFlag());
            }
        });
}

1
投票

流中似乎有一些不正确的括号。还有一些可能的重复代码,我试图减少它们。我还做了一些提取,最终得到了这个:

public void updateFlag(
        Map<DedupeTableEntity, List<DedupeTableEntity>> deltaHashmap,
        Map<DedupeTableEntity, List<DedupeTableEntity>> existingHashmap
) {
    deltaHashmap.values().stream()
            .flatMap(Collection::stream)
            .forEach(k -> extractFlag(existingHashmap, k)
                    .ifPresent(k::setEntityFlag));
}

private Optional<String> extractFlag(Map<DedupeTableEntity, List<DedupeTableEntity>> existingHashmap, DedupeTableEntity k) {
    return existingHashmap.values().stream()
            .flatMap(Collection::stream)
            .filter(e -> equalsByIdAndCountry(k, e))
            .findFirst().map(DedupeTableEntity::getEntityFlag);
}

private boolean equalsByIdAndCountry(DedupeTableEntity c, DedupeTableEntity e) {
    return e.getId().equals(c.getId()) && e.getObjectCountry().equals(c.getObjectCountry());
}

我没有任何数据来测试它是否真的正确,所以我把它留给你。


1
投票

您的代码包含一些错误:

  • 该方法的返回类型为 void,但它尝试返回流。
  • 过滤器操作上对map的调用不是终端,这意味着它不会实际执行映射操作。
  • 要解决这些问题,可以修改该方法以返回修改后的 deltaHashmap

包含返回语句的固定版本:

public HashMap<DedupeTableEntity,List<DedupeTableEntity>> compareTwoHashmaps(
    HashMap<DedupeTableEntity,List<DedupeTableEntity>> deltaHashmap,
    HashMap<DedupeTableEntity,List<DedupeTableEntity>> existingHashmap) {
deltaHashmap.values().stream()
        .flatMap(Collection::stream)
        .filter(c -> existingHashmap.values().stream()
                .flatMap(Collection::stream)
                .anyMatch(e -> e.getId().equals(c.getId()) && e.getObjectCountry().equals(c.getObjectCountry())))
        .forEach(k -> {
            Optional<String> entityFlag = existingHashmap.values().stream()
                    .flatMap(Collection::stream)
                    .filter(e -> e.getId().equals(k.getId()) && e.getObjectCountry().equals(k.getObjectCountry()))
                    .map(r -> r.getEntityFlag())
                    .findFirst();
            entityFlag.ifPresent(k::setEntityFlag);
        });
return deltaHashmap;
}
© www.soinside.com 2019 - 2024. All rights reserved.