为了账号安全,请及时绑定邮箱和手机立即绑定

如何在不覆盖集合的情况下将多个地图放在一起 <Character, Set<String>>

如何在不覆盖集合的情况下将多个地图放在一起 <Character, Set<String>>

侃侃无极 2023-05-24 14:42:16
在我的项目中,我使用了两张地图Map<Character, Set<String>>.map1 - is temporally holding needed valuesmap2 - is summing all data from map1 after each loop例如我得到:map2 = (B; Beryllium, Boron, Bromine)map2 = (H; Hellum, Hydrogen, Hafnium)现在新的 map1 是:map1 = (B; Bismuth)map1 = (O; Oxygen)在我的代码中添加氧气作为新条目是可以的,但是通过覆盖值中的现有数据并只留下铋来为 B 添加新条目结束。我的代码: while (iterator.hasNext()) {   Set<String> words = new TreeSet<>();   String word = iterator.next();   char[] wordChars = word.toCharArray();//some code   words.add(word);   map1.put(wordChars[i], words);}map2.putAll(map1);我很难使用 .merge,但我不知道如何将它与 Sets 作为值一起使用,而且我不能将简单的字符串与 concat 一起使用。
查看完整描述

4 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

您可以像这样使用Map#merge :

Map<String, Set<String>> map1; // [key="B";values=["Beryllium", "Boron", "Bromine"]]

Map<String, Set<String>> map2; // [key="B";values=["Bismuth"] key="I";values=["Iron"]]


for (Entry<String, Set<String>> entry : map2.entrySet()) {

   map1.merge(entry.getKey(), entry.getValue(), (s1, s2) -> {s1.addAll(s2); return s1;});

}


//map1 = [key="B";values=["Beryllium", "Boron", "Bromine", "Bismuth"] key="I";values=["Iron"]]



查看完整回答
反对 回复 2023-05-24
?
慕虎7371278

TA贡献1802条经验 获得超4个赞

在这种情况下不需要临时 map1。获取该字符的集合,如果为空则创建一个新集合。将单词添加到该集合并放入地图中:


 while (iterator.hasNext()) {

   String word = iterator.next();


   //some code 

   Set<String> words = map2.get(word.charAt(0));

   if(words == null) {

     words = new TreeSet<>();

   }

   words.add(word);

   map2.put(word.charAt(0), words);


}


查看完整回答
反对 回复 2023-05-24
?
MM们

TA贡献1886条经验 获得超2个赞

使用 merge() 函数时,如果指定的键尚未与值相关联或值为空,则它将键与给定值相关联。否则,即如果键与一个值相关联,它会用给定的重映射函数的结果替换该值。因此,为了不覆盖旧值,您必须编写重新映射函数,以便它结合旧值和新值。


为此,请替换此行:


map2.putAll(map1);   


map1.forEach( (key, value)->{

        map2.merge(key, value, (value1,value2) -> Stream.of(value1,value2)

                                                        .flatMap(Set::stream)

                                                        .collect(Collectors.toSet()));

    });

这将遍历 map1 并将不存在的 echh 键添加到 map2 并将其与给定值相关联,并且对于已经存在的每个键,它将旧值和新值组合在一起。


或者你也可以使用Map.computeIfPresent和Map.putIfAbsent


map1.forEach( (key, value)->{

        map2.computeIfPresent(key, (k,v) -> Stream.of(v,value).flatMap(Set::stream).collect(Collectors.toSet()));

        map2.putIfAbsent(key, value);

    });


查看完整回答
反对 回复 2023-05-24
?
30秒到达战场

TA贡献1828条经验 获得超6个赞

Map::compute可能是你要找的。这为您提供了一种映射任何现有值(如果有的话)的方法,或者如果没有则提供一个。

例如,在您的情况下,类似以下内容可能就足够了:

oldMap.compute("B", current -> {

    if (current == null) {

        // No existing entry, so use newMap's one

        return newMap.get("B");

    } else {

        // There was an existing value, so combine the Sets

        final Set<String> newValue = new HashSet<>(current);

        newValue.addAll(newMap.get("B"));

        return newValue;

    }

});

还有分别来自 spring 和 guava 的MultiValueMapand Multimap(如果你可以引入依赖项的话)它们已经用更少的工作覆盖了这个案例。



查看完整回答
反对 回复 2023-05-24
  • 4 回答
  • 0 关注
  • 132 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信