[英]Add elements of a list to the same list in java
是否可能以下情况? 如果是,它是否有任何缺点,或者有更好的方法吗?
List<Integer> myList = new ArrayList<>();
myList.add(2);
myList.add(3);
// then add all the elements again
myList.add(myList);
ArrayList
的addAll
方法恰好在Oracle的JDK(和OpenJDK)中工作。 但这并不能保证。 addAll
的Javadoc说:
如果在操作进行过程中修改了指定的集合,则此操作的行为是不确定的。 (这意味着如果指定的集合是此列表,并且此列表是非空的,则此调用的行为是不确定的。)
实际上,这个问题并不像某些答案所暗示的那样毫无意义。 正如这种情况所证明的那样,仅“尝试”还不足以证明某些东西正常工作。
实际上,在考虑list.addAll(list)
是否有效时,您需要问自己如何实现。 如果只是简单地遍历list
并将每个元素添加到list
的末尾,则将得到ConcurrentModificationException
(否则它将陷入无限循环)。 这就是Javadoc不保证此类调用有效的原因。 碰巧的是,Oracle的实现首先将传递的列表复制到数组,然后将数组的每个元素复制到列表的末尾。 这意味着对列表调用addAll
可能不如自己创建列表而不创建额外副本那样有效。
对于基本数据类型(布尔,短,整数,长,浮点,双精度,字符串),它们是不可变的,这意味着它们将始终按值传递。
Integer X = 10;
Integer Y = X; // Y is 10, X is 10
Y = 20; // Y is 20, X is 10
X = 30; // Y is 20, X is 30
String A = "Test";
String B = A; // B is a copy of A; A & B are distinct
但是,当存储对象时会出现问题,如果尝试分配,最终将复制引用而不是复制值。
Object C = new Object();
Object D = C; // C & D points at the same object
最佳实践是复制,否则,如果使用对象,则最终将获得对同一对象的多个引用。
class MyObj { private int val; public MyObj(int v){ val=v; } ..}
ArrayList<MyObj> list = new ArrayList<MyObj>();
list.add(new MyObj(2));
list.add(new MyObj(3));
list.addAll(list);
您可能会认为列表现在有4个对象,除非您错了,它有2个对2个不同对象的引用,一个简单的测试将演示如何。
// prints: 2 3 2 3
for(MyObj m : list) System.out.print(" "+m.getVal());
// modify first item to 5
list.get(0).setVal(5);
// prints: 5 3 5 3
for(MyObj m : list) System.out.print(" "+m.getVal());
您可以通过手动创建和启动对象来克隆对象。
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
MyObj t = new MyObj();
t.setVal(m.getVal());
list.add(t); // append
}
您也可以有一个复制构造函数,然后将要克隆的对象传递给它。
class MyObj
{
..
public MyObj(MyObj o)
{
val = o.getVal();
}
}
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
list.add(new MyObj(m)); // append
}
此外,您的对象类可以实现接口Cloneable
并扩展clone
方法。
class MyObj implements Cloneable
{
..
public Object clone() throws CloneNotSupportedException
{
return (MyObj)super.clone();
}
}
int oldSize = list.size();
for(int i=0; i<oldSize; i++)
{
MyObj m = list.get(i);
list.add(m.clone()); // append
}
myList.add(myList);
的主要缺点 是它不会编译,因为myList
不是Integer
。
但是,您可以使用:
myList.addAll(myList);
要么
myList.addAll(new ArrayList<>(myList));
如果您想安全地这样做。
myList.addAll(myList);
=>有效。
myList.add(myList);
=>无法编译,.add方法需要一个Integer(不是int)作为参数,您不能使用另一个List进行调用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.