如何正确使用 Map <String, StringBuilder> 的 merge() 方法追加特定字符?
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);
在这些映射的基础上,我需要获得一个结果映射,对于上面两个映射中的相同键,具有由“|”分隔的值的串联。
对于不同的键,也必须满足条件 - 如果键仅存在于 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;
map2
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;
预期结果图
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
根本无法完成这项工作。如果 map1
和 map2
都具有提供的密钥,merge
将 仅 调用该函数;否则,如果两个映射中只有一个具有该键的映射,则只插入该映射而不进行修改——因此,没有前导 |
。没有办法让 merge
以不同的方式工作,所以你不能在这里使用它。摆脱它。
像往常一样,如果你只在看起来很明显的地方使用 lambda,而不是像万能的锤子那样好用到你想用它来做任何事情,包括给面包涂黄油,那么阅读起来会更简单。
for (var entry : map2.entrySet()) {
map1
.computeIfAbsent(entry.getKey(), x -> new StringBuilder())
.append("|")
.append(entry.getValue());
}
足够简单,并且完全符合您的要求。
如果你真的铁了心要用那把锤子来涂抹这片面包,你真正想要的方法是compute
。不过,您将不得不摆弄 null
,它不会更漂亮。
注意:collection.forEach
和 collection.stream.forEach
都是糟糕的代码风格——你失去了局部变量、控制流和异常透明度,而且你在交易中一无所获。为什么选择严格劣等的选项?如果您发现转储是可以接受的,例如someList.forEach(System.out::println);
在一行中,我很难想象你可能愿意提供什么样的非疯狂论点来禁止 for (var v : someList) System.out.println(v);
,它同样简短,并且处理本地变量,控制流程和检查异常要好得多。我已经帮您移除了那个钻头。正如我所说,当它们为您提供有形的东西时使用 lambda,例如上面的 computeIfAbsent
。如果没有它们,那会更加复杂。
好吧,这就是我的想法。它只是遍历一个地图,检查键并将适当的值放入另一个地图。如果每个map包含相同的key,则put
,都在map1
中,用|
分隔,否则,将map2 key
和value
放在[=13=中] 与 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
我有以下地图:
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);
在这些映射的基础上,我需要获得一个结果映射,对于上面两个映射中的相同键,具有由“|”分隔的值的串联。
对于不同的键,也必须满足条件 - 如果键仅存在于 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;
map2
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;
预期结果图
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
根本无法完成这项工作。如果 map1
和 map2
都具有提供的密钥,merge
将 仅 调用该函数;否则,如果两个映射中只有一个具有该键的映射,则只插入该映射而不进行修改——因此,没有前导 |
。没有办法让 merge
以不同的方式工作,所以你不能在这里使用它。摆脱它。
像往常一样,如果你只在看起来很明显的地方使用 lambda,而不是像万能的锤子那样好用到你想用它来做任何事情,包括给面包涂黄油,那么阅读起来会更简单。
for (var entry : map2.entrySet()) {
map1
.computeIfAbsent(entry.getKey(), x -> new StringBuilder())
.append("|")
.append(entry.getValue());
}
足够简单,并且完全符合您的要求。
如果你真的铁了心要用那把锤子来涂抹这片面包,你真正想要的方法是compute
。不过,您将不得不摆弄 null
,它不会更漂亮。
注意:collection.forEach
和 collection.stream.forEach
都是糟糕的代码风格——你失去了局部变量、控制流和异常透明度,而且你在交易中一无所获。为什么选择严格劣等的选项?如果您发现转储是可以接受的,例如someList.forEach(System.out::println);
在一行中,我很难想象你可能愿意提供什么样的非疯狂论点来禁止 for (var v : someList) System.out.println(v);
,它同样简短,并且处理本地变量,控制流程和检查异常要好得多。我已经帮您移除了那个钻头。正如我所说,当它们为您提供有形的东西时使用 lambda,例如上面的 computeIfAbsent
。如果没有它们,那会更加复杂。
好吧,这就是我的想法。它只是遍历一个地图,检查键并将适当的值放入另一个地图。如果每个map包含相同的key,则put
,都在map1
中,用|
分隔,否则,将map2 key
和value
放在[=13=中] 与 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