Изменение значения после его размещения в HashMap меняет то, что находится внутри HashMap? - PullRequest
33 голосов
/ 01 июня 2009

Если я создам новый HashMap и новый список, а затем помещаю список в Hashmap с каким-то произвольным ключом, а затем вызываю List.clear(), повлияет ли это на то, что я поместил в HashMap?

Более глубокий вопрос здесь заключается в следующем: когда я добавляю что-то в HashMap, копируется и помещается ли новый объект или размещается ссылка на исходный объект?

Спасибо!

Ответы [ 8 ]

44 голосов
/ 01 июня 2009

Здесь происходит то, что вы помещаете указатель на список в хэш-карте, а не на сам список.

Когда вы определяете

List<SomeType> list;

вы определяете указатель на список, а не сам список.

Когда вы делаете

map.put(somekey, list);

вы просто храните копию указателя , а не списка.

Если где-то еще вы следуете этому указателю и изменяете объект в его конце, любой, кто держит этот указатель, все равно будет ссылаться на тот же измененный объект.

Подробную информацию о передаче по значению в Java см. В http://javadude.com/articles/passbyvalue.htm.

11 голосов
/ 01 июня 2009

Java является передачей по ссылке по значению.

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

3 голосов
/ 01 июня 2009

Когда я добавляю что-то в HashMap, новый объект скопирован и размещен или является ссылка на исходный объект размещены

Это всегда ссылка на объект. Если вы очистите HashMap, объект все еще будет «живым». Тогда объект будет уничтожен сборщиком мусора, если никто больше на него не ссылается. Если вам нужно скопировать его, взгляните на метод Object.clone () и интерфейс Cloneable

2 голосов
/ 16 июня 2015
Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
  1. Копировать по ссылке: Если вы присваиваете одну HashMap другой, то обе указывают на одну и ту же ссылку в памяти.

    Карта hasmapB;

    hashmapB = hashmapA;

Если вы внесете изменения в любой из них, изменения будут отражены в обоих HashMap , так как оба ссылаются на одно и то же местоположение.

  1. Скопировать по значению: Если вы хотите

клонирование / глубокая копия / создание отдельной ячейки памяти / создание отдельного объекта

из hashmapB при копировании содержимого hashmapA

Map<Integer, Integer> hashmapB = new HashMap<>();;

hashmapB.putAll(hashmapA)

Примечание: ** Вы заметили разницу в обоих пунктах для объявления hashmapB? Во втором пункте мы должны вызвать конструктор ** HashMap . Так что мы можем поместить все данные hashmapA в hashmapB.

Ссылка

1 голос
/ 15 июля 2013

Правильный ответ для этого объяснен ниже: Предположим, у вас есть HashMap с именем hashmap, и изначально вы помещаете пару ключ-значение в этот HashMap, например. HashMap < "test1", "test2">. После этого, когда вы передаете этот hashmap в функцию, где вы снова изменяете ее значение на test3, например hashmap.put ("test1", "test3"), и снова печатаете карту в основном методе, Java Pass by Value Concept терпит неудачу. 1001 *

Причина: Когда вы используете HashMap, он выполняет хеширование для ключа (test1) и сохраняет значение. Когда вы передаете его в функцию, где он снова меняет свое значение, он снова выполняет хеширование для того же ключа и получает тот же адрес памяти и соответственно изменяет значение. Вот почему, когда вы пытаетесь получить ключ «test1», он выдает результат как «test3»

1 голос
/ 28 апреля 2010

Попробуйте

package test32;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

class Foo {
    public Foo(int id, String name) {
 this.id=id;
 this.name=name;
    }

    public static void main(String[] args) {
 HashMap strs = new HashMap();

 // create a list of objects
 List ls = new ArrayList();
 ls.add(new Foo(1, "Stavros"));
 ls.add(new Foo(2, "Makis"));
 ls.add(new Foo(3, "Teo"));
 ls.add(new Foo(4, "Jim"));

 // copy references of objects from list to hashmap
 strs.put("1", ls.get(0));
 strs.put("2", ls.get(1));
 strs.put("3", ls.get(2));
 strs.put("4", ls.get(3));

 System.out.println("list before change  : " + ls);
 System.out.println("map before change: " + strs);
 // get an object from the hashmap
 Foo f=strs.get("1");
 // set a different value
 f.setId(5);
 // observe that the differences are reflected to the list and to the hashmap also
 System.out.println("list after change  : "+ls);
 System.out.println("map after change: "+strs);
    }

    private int id;
    public void setId(int id) {
 this.id=id;
    }
    public int getId() {
 return this.id;
    }

    private String name;
    public void setName(String name) {
 this.name=name;
    }
    public String getName() {
 return this.name;
    }

    public String toString() {
 StringBuilder sb = new StringBuilder();
 sb.append(id);
 sb.append("-");
 sb.append(name);
 return sb.toString();
    }
}
1 голос
/ 01 июня 2009

Обычно вы всегда имеете дело со ссылками в Java (если только вы сами не создаете новый объект с помощью "new" [1]).

Следовательно, это ссылка, а не полная копия объекта, которую вы сохранили на карте, и изменение списка также повлияет на то, что вы видите при просмотре карты.

Это особенность, а не ошибка:)

[1] Пуритане будут включать «clone ()» и сериализацию, но для большинства Java-кода «новый» - это способ получения объектов.

0 голосов
/ 01 июня 2009

Боже, люди ... все в Java передается по значению. Когда вы передаете объект, передаваемое вами значение является ссылкой на объект. В частности, вы передаете копию ссылки на объект. В Java также нет указателей, хотя ссылки похожи. Получите это правильно!

...