简体   繁体   English

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

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

I have the following maps:我有以下地图:

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

On the basis of these maps, I need to obtain a result map that for identical keys in both maps above has a concatenation of values separated by "|".在这些映射的基础上,我需要获得一个结果 map,对于上面两个映射中的相同键,它具有由“|”分隔的值的串联。

For different keys also the condition must be met - if the key is present only in map1 then only the value is added, and if the key is present only in map2 then "|"对于不同的键,还必须满足条件 - 如果键仅存在于 map1 中,则仅添加值,如果键仅存在于 map2 中,则“|” should be added before the value.应该在值之前添加。 In short, I mean this result:简而言之,我的意思是这个结果:

map1地图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地图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;

expected result map预期结果 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;

I almost managed to find a solution but I have a problem with the case when the key only exists in map2, I have no idea how to change my code so that the "|"我几乎设法找到了解决方案,但是当密钥仅存在于 map2 中时,我遇到了问题,我不知道如何更改我的代码以使“|” sign is added in front of the value.在值前面添加符号。

How can I fix it?我该如何解决?

My code:我的代码:

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

Result:结果:

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 simply cannot do the job. merge根本无法完成这项工作。 merge will only invoke that function if both map1 and map2 have the provided key;如果map1map2都具有提供的密钥,则merge只会调用 function; otherwise, if only one of the two maps has a mapping for that key, that mapping is just inserted, without modification - thus, no leading |否则,如果两个映射中只有一个具有该键的映射,则仅插入该映射,无需修改-因此,没有前导| . . There is no way to make merge work differently, so you just cannot use it here.没有办法让merge工作不同,所以你不能在这里使用它。 Get rid of it.摆脱它。

As usual, it's just simpler to read if you use lambdas only where they seem like a clear win, instead of as the universal hammer that is so good you want to use it for everything, including buttering your bread.像往常一样,如果你只在看起来很明显的地方使用 lambda,而不是作为万能的锤子,你想用它来做任何事情,包括给面包涂黄油,那么阅读起来会更简单。

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

Simple enough, and does precisely what you want.足够简单,并且完全按照您的意愿行事。

If you really are hell bent on using that hammer to smear this slice of bread, the method you really want is compute .如果你真的一心想用那把锤子来涂抹这片面包,你真正想要的方法是compute You'll have to mess around with null though, it's not going to be any prettier.不过,您将不得不弄乱null ,它不会更漂亮。

NB: collection.forEach , as well as collection.stream.forEach are bad code style - you lose local variable, control flow, and exception transparency, and you gain absolutely nothing whatsoever in trade.注意: collection.forEachcollection.stream.forEach是糟糕的代码风格——你失去了局部变量、控制流和异常透明度,你在交易中一无所获。 Why pick a strictly inferior option?为什么要选择严格劣等的选项? If you find it acceptable to dump eg someList.forEach(System.out::println);如果您发现转储例如someList.forEach(System.out::println);是可以接受的on a single line, I'm having a hard time imagining what kind of non-crazy argument you might care to provide for disallowing for (var v: someList) System.out.println(v);在一行中,我很难想象你可能会关心提供什么样的非疯狂论点来禁止for (var v: someList) System.out.println(v); , which is just as short, and deals with local vars, control flow, and checked exceptions much better. ,它同样简短,并且可以更好地处理本地变量、控制流和检查异常。 I've done you the service of removing that bit.我已经为您完成了删除该位的服务。 As I said, use lambdas when they get you something tangible, such as the computeIfAbsent above.正如我所说,当 lambdas 为您提供有形的东西时使用它们,例如上面的computeIfAbsent That'd be far more convoluted without them.如果没有他们,那会更加复杂。

Well, here is what I came up with.好吧,这就是我想出的。 It simply iterates over one map checking the keys and putting the appropriate values in the other map.它只是遍历一个 map 检查键并将适当的值放入另一个 map。 If each map contains the same key, then put , both in map1 separated by |如果每个 map 包含相同的密钥, put , 都放在map1中,用|分隔, otherwise, put the map2 key and value in map1 with the prefixed with | , 否则,将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);

Prints印刷

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;

If you want them sorted by key, then make map1 a TreeMap如果您希望它们按键排序,则将map1 TreeMap

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

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