Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why java "putAll" cannot deep copy Map's value elements?

I got this code snippet:

public static void main(String[] args){
    Map<String, Set<String>> map = new HashMap<>();
    Set<String> set = new HashSet<>();
    set.add("user1");
    set.add("user2");
    map.put("key1", set);

    Map<String, Set<String>> map2 = new HashMap<>();
    map2.putAll(map);// I expect all elements are copied

    map.get("key1").add("user3");// add 1 element in "map"
    System.out.println(map2.get("key1").size()); // "map2" was affected
}

In fact the modification of map's set element affected map2, so the program prints "3" instead of "2"

This is weird, I expect that, as long as I used "putAll" method for the new map2 construction, I think both key and value should be deeply cloned?

How to fix my program and make sure map2 is completed divided from map, while copying all elements from map?

Thanks

like image 214
Hind Forsum Avatar asked Nov 18 '25 02:11

Hind Forsum


2 Answers

putAll copies references of the keys and values. It does not make copies of the instances referenced by those references.

You'll have to loop (or stream) over the original Map and create copies of all the value Sets:

Map<String, Set<String>> map2 =
    map.entrySet()
       .stream()
       .collect(Collectors.toMap(Map.Entry::getKey,e-> new HashSet<>(e.getValue())));

Note that there's no need to create copies of the keys, since String is immutable.

like image 174
Eran Avatar answered Nov 20 '25 16:11

Eran


Another way:

Map<String, Set<String>> map2 = new HashMap<>();
map2.putAll(map);

map2.replaceAll((k, v) -> new HashSet<>(v));
like image 30
fps Avatar answered Nov 20 '25 16:11

fps



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!