2015-10-28 4 views
1

У меня возникли проблемы с реализацией HashMaps с ArrayLists в моем классе java. Дело в том, что добавление объектов к ArrayList - это HashMap, хотя я не обновляю свои HashMap.Проблема с использованием HashMaps с ArrayList

Это код, который я не могу понять, как работает:

HashMap<String, ArrayList<String>> map = new HashMap<>(); 

ArrayList<String> array = new ArrayList<String>(); 
array.add("One"); 
array.add("Two"); 

map.put("Key", array); 

array.add("Three"); //2. Why does this get added to the HashMap? 

System.out.println(map1.get("Key")); 
//1. This print out [One, Two, Three].. When it should be [One, Two]! 
+4

Вот как ссылки работают в Java. То, что вы положили на карту, является ссылкой на список, поэтому любые изменения в списке будут отображаться при печати карты. –

+0

'add()' не копирует список, он просто вставляет ссылку. – Andreas

+0

Так работает Java. map.getKey («Ключ») и ваша переменная массива ссылаются на одно и то же местоположение в памяти. Добавляете ли вы элемент через ссылку «массив» или через ссылку, возвращаемую map.getKey («ключ»), вы добавляете элементы в одно и то же место в памяти. – bdkosher

ответ

3

ArrayList передается по ссылке map.put(). Это означает отсутствие копирования, после вызова ваша переменная array относится к одному и тому же объекту. При копировании при добавлении записи, то он будет работать: map.put("Key", new ArrayList<String>(array));

1
map.put("Key", array); 

Это означает, что вы добавляете ссылку на list к map. Следовательно, изменения этой ссылки можно увидеть повсюду.

Если вы не хотите этого делать, создайте новый список и добавьте его.

1

Это ожидаемое поведение. Вы помещаете список в карту, а не в копию, сам список. Поэтому, если позднее вы измените список, список внутри карты (который является фактическим списком) также будет изменен.

1

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

Помните, что Java передает ссылки на объекты вокруг (а не копии), и если у вас есть изменяемый объект, на который делается ссылка в контейнере, этот объект все еще можно изменить.

Если вы хотите этого не делать, вам необходимо сделать defensive copy. Обратите внимание, что это относится к изменяемым объектам в целом (а не только к коллекциям), и вам нужно быть ясными, когда вы передаете ссылки и удерживаете их, чтобы кто-либо еще, содержащий эту ссылку, мог изменять/мутировать ваш объект без вашего контроля. Часто предпочтительнее создавать и пропускать immutable объектов, а не

0

Вы добавляете ссылку своего ArrayList в качестве значения для вашего map.

так что если вы хотите только первые два значения, вы можете просто указать свой ArrayList в null, чтобы убедиться, что вы не добавить материал к нему затем повторно инициировать его

HashMap<String, ArrayList<String>> map = new HashMap<>(); 

ArrayList<String> array = new ArrayList<String>(); 
array.add("One"); 
array.add("Two"); 

map.put("Key", array); 

array=null; //note this isn't really necessary, just a precaution that you won't change the value of arraylist inside the map using this refrence 
array=new ArrayList<String>(map.get("key")); 
array.add("Three"); 

System.out.println(map1.get("Key")); 

выход:

[один, два]

+0

Почему нужно сначала установить 'array' в' null' ? – Tom

+0

@ Тому не обязательно, я просто добавлял заметку, чтобы сказать как предосторожность. его хорошая практика – nafas

+0

Хорошая практика? Где? Этот шаг не имеет значения. – Tom

Смежные вопросы