在其他arraylist上执行addAll时,两个arraylists都引用相同的元素

时间:2018-05-14 06:39:26

标签: java arraylist collections

当我将ArrayList的所有内容添加到另一个ArrayList时,另一个ArrayList包含对第一个ArrayList元素的引用。因此,当我更改List s中的任何一个元素时,另一个List中的相应元素也会发生变化。这显然意味着addAll会分配对新List的引用。

参考代码:

ArrayList<StringBuffer> a = new ArrayList<>();
a.add(new StringBuffer("1"));
a.add(new StringBuffer("2"));
a.add(new StringBuffer("3"));

ArrayList<StringBuffer> b = new ArrayList<>();
b.addAll(a);

System.out.println("Arralists" + " before: ");
System.out.println("A arraylist" + a.toString());
System.out.println("B arraylist" + b.toString() + "\n\n");

a.set(0, a.get(0).replace(0, 1, String.valueOf(4)));

System.out.println("Arralists after " + "updating a: ");
System.out.println("A arraylist" + a.toString());
System.out.println("B arraylist" + b.toString() + "\n\n");

对应日志:

Arralists before: 
A arraylist[1, 2, 3]
B arraylist[1, 2, 3]


Arralists after updating a: 
A arraylist[4, 2, 3]
B arraylist[4, 2, 3]

我想知道避免引用和创建副本数组的最佳方法。

修改

我想在android中执行此操作。 @Eran提出了Java8的答案,但兼容性问题就出现了。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:6)

  

这显然意味着addall会为新列表分配引用。

那是对的。

  

我想知道避免引用和创建副本数组的最佳方法。

不要使用addAll。迭代输入List并创建List的每个元素的副本。

例如,使用Java 8 Stream并利用现有的复制构造函数StringBuffer(CharSequence seq)

List<StringBuffer> b = a.stream().map(StringBuffer::new).collect(Collectors.toList());

如果没有Stream,您可以使用for循环:

List<StringBuffer> b = new ArrayList<>();
for (StringBuffer sb : a) {
    b.add(new StringBuffer(sb));
}