将列表元素添加到java中的相同列表中

时间:2017-04-30 21:42:39

标签: java list arraylist

以下是否可能?如果是,它有任何缺点或有更好的方法吗?

List<Integer> myList = new ArrayList<>();
myList.add(2);
myList.add(3);

// then add all the elements again
myList.add(myList);

4 个答案:

答案 0 :(得分:3)

addAll的{​​{1}}方法恰好在Oracle的JDK(和OpenJDK)中有效。但不能保证。 Javadoc for addAll说:

  

如果在操作过程中修改了指定的集合,则此操作的行为是不确定的。 (这意味着如果指定的集合是此列表,则此调用的行为是未定义的,并且此列表是非空的。)

这个问题实际上并不像一些答案所暗示的那样毫无意义。正如本例所证明的那样,仅仅“尝试它”并不足以让某些东西正确运行。

事实上,在考虑ArrayList是否有效时,您需要问问自己如何实施。如果它只是迭代list.addAll(list)并将每个元素添加到list的末尾,那么您将获得list(否则它将进入无限循环)。这就是为什么Javadoc不保证这样的调用有效的原因。碰巧,Oracle的实现首先将传递的列表复制到数组,然后将数组的每个元素复制到列表的末尾。这意味着为列表调用ConcurrentModificationException可能不如在不创建额外副本的情况下自行完成。

答案 1 :(得分:2)

对于基本数据类型(Boolean,Short,Integer,Long,Float,Double,String),它们是不可变的,这意味着它们将始终按值传递。

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个不同的对象,一个简单的测试将显示如何。

// 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
}

答案 2 :(得分:1)

myList.add(myList);的主要缺点是它无法编译,因为myList不是Integer

但是,您可以使用:

myList.addAll(myList);

Ideone demo

myList.addAll(new ArrayList<>(myList));

如果你想安全地做到这一点。

答案 3 :(得分:0)

myList.addAll(myList);

=&GT;的工作原理。

myList.add(myList); 

=&GT;不会编译,.add方法需要一个Integer(不是int)作为参数,你不能使用另一个List调用。