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

par*_*i26 1 java collections arraylist

当我将a的所有内容添加ArrayList到另一个时ArrayList,另一个ArrayList包含对第一个元素的引用ArrayList.因此,当我更改Lists 中的任何一个元素时,另一个元素中的相应元素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");
Run Code Online (Sandbox Code Playgroud)

对应日志:

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]
Run Code Online (Sandbox Code Playgroud)

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

编辑

我想在android中做到这一点.@Eran提出了Java8的答案,但兼容性问题就出现了.任何帮助将不胜感激.

Era*_*ran 6

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

那是对的.

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

不要用addAll.迭代输入List并创建其中每个元素的副本List.

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

List<StringBuffer> b = a.stream().map(StringBuffer::new).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

没有Streams,你可以使用for循环:

List<StringBuffer> b = new ArrayList<>();
for (StringBuffer sb : a) {
    b.add(new StringBuffer(sb));
}
Run Code Online (Sandbox Code Playgroud)