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

时间:2019-08-07 08:05:32

标签: java sorting dictionary merge set

在我的项目中,我正在使用两张地图Map<Character, Set<String>>.

map1 - is temporally holding needed values
map2 - 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 个答案:

答案 0 :(得分:1)

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中分别有MultiValueMapMultimap(如果可以引入依赖项),已经可以用较少的工作来解决这种情况。

答案 1 :(得分:1)

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

 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);

}

答案 2 :(得分:1)

您可以像这样使用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"]]

答案 3 :(得分:1)

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

为此,请替换此行:

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.computeIfPresentMap.putIfAbsent

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