HashSet是否为已添加的对象制作内部副本?

时间:2012-10-24 10:53:48

标签: java reference

假设我有一个递归函数,就像这样

public void someRecur(List<Integer>someList){
  if(someBreakCondition)
    Set.add(someList);
  for(int i = 0; i < someLen ; i++){
    someList.add(someInt);
    someRecur(someList);
    someList.remove(someInt);
   }
}

删除会影响已放入集合的列表吗?如何为集合提供列表的实际副本?

5 个答案:

答案 0 :(得分:3)

您不会将对象放入地图中;您将引用添加到堆上的对象。

Java数据结构保存对象的引用,而不是对象本身。如果从数据结构中删除引用,则其他对象可能仍具有该引用的副本。

如果两个对象持有对可变对象的引用,则每个对象将看到另一个对象所做的更改。 (这就是线程安全很重要的原因。)

当没有人引用堆上的对象时,它符合GC的条件。

答案 1 :(得分:3)

  

删除会影响已放入集合的列表吗?

是的,它会受到影响。您放入Set中的内容不是实际列表,而是对该列表的引用。因此,当修改列表时,指向该列表的所有引用都将看到更改。

  

如何为集合提供列表的实际副本?

因为,您可以创建新列表,并将原始列表中的所有元素添加到该列表并将其添加到Set -

List<Integer> newList = new ArrayList<Integer>();
newList.addAll(someList);
set.addAll(newList);

或者,简单地说: -

set.addAll(new ArrayList<Integer>(someList));

答案 2 :(得分:2)

不,HashSet不会复制您添加到其中的对象。

答案 3 :(得分:2)

我必须警告你,在将对象放入集合后不得更改对象 - 这就是你在代码中所做的事情:你将列表添加到集合中然后更新事后呢。这弄乱了它的哈希码并打破了HashSet。也许你甚至不需要那里的Set,而是另一个列表。

您可以通过克隆(如其他地方所建议)或通过明确构建new ArrayList(someList)来轻松地将列表的安全副本添加到集合中。

答案 4 :(得分:1)

该集将保留对列表的引用 - 因此只有一个列表。您可以直接在原始列表中添加/删除项目,也可以使用集合中的列表:它将具有相同的效果。