放入HashMap后更改值会改变HashMap中的内容吗?

时间:2009-06-01 13:15:56

标签: java hashmap pass-by-reference

如果我创建一个新的HashMap和一个新的List,然后用一些任意键将List放在Hashmap中,然后调用List.clear()它会影响我在HashMap中放置的内容吗?

这里更深层次的问题是:当我向HashMap添加内容时,是复制并放置了一个新对象还是对放置的原始对象的引用?

谢谢!

8 个答案:

答案 0 :(得分:44)

这里发生的是你将指针放在hashmap中的列表中,而不是列表本身。

定义时

List<SomeType> list;

您正在定义指向列表的指针,而不是列表本身。

当你这样做时

map.put(somekey, list);

你只是存储指针的副本,而不是列表。

如果在其他地方,你遵循该指针并在其末尾修改对象,那么持有该指针的任何人仍将引用相同的修改对象。

有关Java中传递值的详细信息,请参阅http://javadude.com/articles/passbyvalue.htm

答案 1 :(得分:11)

Java是按值传递的。

将列表添加到哈希映射只会添加对哈希映射的引用,该哈希映射指向相同的列表。因此,直接清除列表确实会清除您在散列映射中引用的列表。

答案 2 :(得分:3)

  

当我向HashMap添加内容时,是   复制和放置的新对象或是   引用原始对象   放置?

始终是对象的引用。 如果清除HashMap,对象仍将是“实时”。 然后,如果没有人再引用它,该对象将被垃圾收集器销毁。 如果需要复制它,请查看Object.clone()方法和Cloneable接口

答案 3 :(得分:2)

Map<Integer, Integer> hasmapA = new HashMap<>();
hasmapA.put("key1", "value1");
hasmapA.put("key2", "value2");
hasmapA.put("key3", "value3");
  1. 按引用复制:如果您将一个 HashMap 分配给其他人,则两者都指向内存中的相同引用。

    映射hasmapB;

    hashmapB = hashmapA;

  2. 如果您对其中任何一项进行了更改,则更改将反映在 HashMap 中,因为两者都引用了相同的位置。

    1. 按值复制:如果您要
    2.   

      clone / deepcopy /创建单独的内存位置/创建单独的对象

      复制hashmapA的内容时,hashmapB的

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

      注意:** 您是否注意到hashmapB声明的两个点的差异?在第二点,我们必须调用** HashMap 构造函数。这样我们就可以将hashmapA的 putAll 数据放入hashmapB。

      Reference

答案 4 :(得分:1)

通常你总是在Java中处理引用(除非你用“new”[1]自己明确地创建一个新对象。)

因此,它是一个参考,而不是您存储在地图中的完整对象副本,更改列表也会影响您在浏览地图时看到的内容。

这是一个功能,而不是一个错误:)

[1]清教徒将包括“clone()”和序列化,但对于大多数java代码,“new”是获取对象的方式。

答案 5 :(得分:1)

试一试

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

答案 6 :(得分:1)

对此的正确答案解释如下: 假设您有一个名为hashmap的HashMap,并且最初在此HashMap中放置一个键值对,例如散列映射&LT; “测试1”, “test2的” 取代。 在此之后,当您将此hashmap传递给一个函数,在该函数中,您再次将其值更改为test3,如hashmap.put(“test1”,“test3”)并再次在main方法中打印映射,此时Java Pass by Value Concept将失败。 / p>

原因是: 当您使用HashMap时,它会为密钥(test1)执行散列并存储该值。当您将它传递给它再次更改其值的函数时,它再次对同一个键执行散列并获取相同的内存地址并更改值。 这就是为什么当你试图检索关键字“test1”时它给你的结果为“test3”

答案 7 :(得分:-2)

Geeze people ...... Java中的一切都是通过价值传递的。传递对象时,传递的值是对象引用。具体来说,您传递的是对象引用的副本。 Java中也没有指针,尽管引用类似。做对了!