Почему java "putAll" не может глубоко копировать элементы значения Map? - PullRequest
0 голосов
/ 13 ноября 2018

Я получил этот фрагмент кода:

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
}

На самом деле модификация элемента набора карты повлияла на map2, поэтому программа выводит «3» вместо «2»

Это странно, я ожидаю, что, пока я использовал метод "putAll" для новой конструкции map2, я думаю, что и ключ, и значение должны быть глубоко клонированы?

Как исправить мою программу и убедиться, что map2 завершена, отделена от карты, копируя при этом все элементы с карты?

Спасибо

Ответы [ 2 ]

0 голосов
/ 13 ноября 2018

Другой способ:

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

map2.replaceAll((k, v) -> new HashSet<>(v));
0 голосов
/ 13 ноября 2018

putAll копирует ссылки на ключи и значения.Он не создает копии экземпляров, на которые ссылаются эти ссылки.

Вам придется выполнить цикл (или поток) поверх оригинального Map и создать копии всех значений Set s:

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

Обратите внимание, что создавать копии ключей не нужно, поскольку String является неизменным.

...