繁体   English   中英

如何正确使用 Map 的方法 merge()<string, stringbuilder> 到 append 一个特定的字符?</string,>

[英]How to correctly use the method merge() of Map <String, StringBuilder> to append a specific character?

我有以下地图:

Map<String, StringBuilder> map1 = new HashMap<>();
Map<String, StringBuilder> map2 = new HashMap<>();

StringBuilder sb11 = new StringBuilder("0004001:00:00;0004002:00:00;0004002:01:01;");
StringBuilder sb12 = new StringBuilder("0005001:00:00;0005002:00:00;0005002:01:01;");
StringBuilder sb13 = new StringBuilder("0007001:00:00;0007002:00:00;0007002:01:01;");
  
map1.put("0004", sb11);
map1.put("0005", sb12);
map1.put("0007", sb13);
  
StringBuilder sb21 = new StringBuilder("0004002:00:00;0004002:00:00;0004002:01:01;");
StringBuilder sb22 = new StringBuilder("0007002:00:00;0007002:00:00;0007002:01:01;");
StringBuilder sb23 = new StringBuilder("0008002:00:00;0008002:00:00;0008002:01:01;");
  
map2.put("0004", sb21);
map2.put("0007", sb22);
map2.put("0008", sb23);

在这些映射的基础上,我需要获得一个结果 map,对于上面两个映射中的相同键,它具有由“|”分隔的值的串联。

对于不同的键,还必须满足条件 - 如果键仅存在于 map1 中,则仅添加值,如果键仅存在于 map2 中,则“|” 应该在值之前添加。 简而言之,我的意思是这个结果:

地图1

0004 - 0004001:00:00;0004002:00:00;0004002:01:01;
0005 - 0005001:00:00;0005002:00:00;0005002:01:01;
0007 - 0007001:00:00;0007002:00:00;0007002:01:01;

地图2

0004 - 0004002:00:00;0004002:00:00;0004002:01:01;
0007 - 0007002:00:00;0007002:00:00;0007002:01:01;
0008 - 0008002:00:00;0008002:00:00;0008002:01:01;

预期结果 map

0004 - 0004001:00:00;0004002:00:00;0004002:01:01;|0004002:00:00;0004002:00:00;0004002:01:01;
0005 - 0005001:00:00;0005002:00:00;0005002:01:01;
0007 - 0007001:00:00;0007002:00:00;0007002:01:01;|0007002:00:00;0007002:00:00;0007002:01:01;
0008 - |0008002:00:00;0008002:00:00;0008002:01:01;

我几乎设法找到了解决方案,但是当密钥仅存在于 map2 中时,我遇到了问题,我不知道如何更改我的代码以使“|” 在值前面添加符号。

我该如何解决?

我的代码:

public static void main(String args[]) {

    Map<String, StringBuilder> map1 = new HashMap<>();
    Map<String, StringBuilder> map2 = new HashMap<>();

    StringBuilder sb11 = new StringBuilder("0004001:00:00;0004002:00:00;0004002:01:01;");
    StringBuilder sb12 = new StringBuilder("0005001:00:00;0005002:00:00;0005002:01:01;");
    StringBuilder sb13 = new StringBuilder("0007001:00:00;0007002:00:00;0007002:01:01;");
      
    map1.put("0004", sb11);
    map1.put("0005", sb12);
    map1.put("0007", sb13);
      
    StringBuilder sb21 = new StringBuilder("0004002:00:00;0004002:00:00;0004002:01:01;");
    StringBuilder sb22 = new StringBuilder("0007002:00:00;0007002:00:00;0007002:01:01;");
    StringBuilder sb23 = new StringBuilder("0008002:00:00;0008002:00:00;0008002:01:01;");
      
    map2.put("0004", sb21);
    map2.put("0007", sb22);
    map2.put("0008", sb23);

      
      //Merge maps
      map2.forEach((key, value) -> map1.merge(key, value, (v1, v2) -> v1.append("|").append(v2)));
      
      map1.entrySet().forEach(entry->{
        System.out.println(entry.getKey() + " " + entry.getValue());  
    });
}

结果:

0007 0007001:00:00;0007002:00:00;0007002:01:01;|0007002:00:00;0007002:00:00;0007002:01:01;
0004 0004001:00:00;0004002:00:00;0004002:01:01;|0004002:00:00;0004002:00:00;0004002:01:01;
0005 0005001:00:00;0005002:00:00;0005002:01:01;
0008 0008002:00:00;0008002:00:00;0008002:01:01;

merge根本无法完成这项工作。 如果map1map2都具有提供的密钥,则merge只会调用 function; 否则,如果两个映射中只有一个具有该键的映射,则仅插入该映射,无需修改-因此,没有前导| . 没有办法让merge工作不同,所以你不能在这里使用它。 摆脱它。

像往常一样,如果你只在看起来很明显的地方使用 lambda,而不是作为万能的锤子,你想用它来做任何事情,包括给面包涂黄油,那么阅读起来会更简单。

for (var entry : map2.entrySet()) {
     map1
       .computeIfAbsent(entry.getKey(), x -> new StringBuilder())
       .append("|")
       .append(entry.getValue());
}

足够简单,并且完全按照您的意愿行事。

如果你真的一心想用那把锤子来涂抹这片面包,你真正想要的方法是compute 不过,您将不得不弄乱null ,它不会更漂亮。

注意: collection.forEachcollection.stream.forEach是糟糕的代码风格——你失去了局部变量、控制流和异常透明度,你在交易中一无所获。 为什么要选择严格劣等的选项? 如果您发现转储例如someList.forEach(System.out::println);是可以接受的在一行中,我很难想象你可能会关心提供什么样的非疯狂论点来禁止for (var v: someList) System.out.println(v); ,它同样简短,并且可以更好地处理本地变量、控制流和检查异常。 我已经为您完成了删除该位的服务。 正如我所说,当 lambdas 为您提供有形的东西时使用它们,例如上面的computeIfAbsent 如果没有他们,那会更加复杂。

好吧,这就是我想出的。 它只是遍历一个 map 检查键并将适当的值放入另一个 map。 如果每个 map 包含相同的密钥, put , 都放在map1中,用|分隔 , 否则,将map2 keyvalue放在map1中, prefixed| .

for(String key : map2.keySet()) {
    if (map1.containsKey(key)) {
        map1.put(key, map1.get(key).append("|").append(map2.get(key)));
    } else {
        map1.put(key, map2.get(key).insert(0, "|"));
    }
}
    
map1.entrySet().forEach(System.out::println);

印刷

0007=0007001:00:00;0007002:00:00;0007002:01:01;|0007002:00:00;0007002:00:00;0007002:01:01;
0004=0004001:00:00;0004002:00:00;0004002:01:01;|0004002:00:00;0004002:00:00;0004002:01:01;
0005=0005001:00:00;0005002:00:00;0005002:01:01;
0008=|0008002:00:00;0008002:00:00;0008002:01:01;

如果您希望它们按键排序,则将map1 TreeMap

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM