当我将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的答案,但兼容性问题就出现了。任何帮助将不胜感激。
答案 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));
}