2017-04-30 9 views
0

次は可能ですか?はいの場合、それには欠点がありますか、これを行うにはより良い方法がありますか?リストの要素をjavaの同じリストに追加

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

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

試しましたか?試してみると、何かが可能かどうかをテストする最良の方法です。 – DyZ

+0

実際には 'for'ループを使用して伝統的な方法で行うことができます –

答えて

1

myList.add(myList);との主な欠点は、myListIntegerではないので、それは、コンパイルされませんということです。

あなたは、しかし、使用することができます。

myList.addAll(myList); 

Ideone demo

または

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

あなたが安全にそれをしたい場合。

0
myList.addAll(myList); 

=>動作します。

myList.add(myList); 

=>コンパイルされませんが、.addメソッドは、引数として整数(int型ではない)が必要で、あなたは別のリストを使用して呼び出すことはできません。

+0

これはOracleの実装では機能しますが、API仕様で動作することは保証されていません(詳細は私の回答を参照してください) –

3

addAllメソッドArrayListは、OracleのJDK(およびOpenJDK)で動作します。しかし、それは保証されていません。 Javadoc for addAllのコメント:

操作の進行中に指定されたコレクションが変更されると、この操作の動作は未定義です。指定されたコレクションがこのリストであり、このリストが空でない場合、この呼び出しの動作は未定義であることを意味します。この事例が証明するように、「試してみる」だけでは、何かが正しく動作するかどうかの十分なテストではありません。

実際、list.addAll(list)が機能するかどうかを考えるとき、どのように実装されているのか自分に尋ねる必要があります。単純にlistを繰り返して、各要素をlistの末尾に追加すると、ConcurrentModificationException(またはそれ以外の場合は無限ループになります)が表示されます。そのため、Javadocはそのような呼び出しが動作することを保証しません。 Oracleの実装は、渡されたリストを配列にコピーした後、配列の各要素をリストの最後にコピーします。つまり、リストのためにaddAllを呼び出すと、余分なコピーを作成せずに自分で行うよりも効率的ではない可能性があります。

+0

お勧めしますか? – daljit97

+0

@ daljit97これを安全に行う方法を示す2つの回答のいずれか。 Andy Turnerは 'myList.addAll(new ArrayList <>(myList));'を表示します。これは簡潔であるという利点がありますが、Oracleの実装でも別のコピーが作成されても、 'myList'のコピーが作成されます。これはもっと読みやすいので、私の好む方法ですが、リストが非常に長く、余分なコピーを作成するのに十分なメモリがない場合は、 'get(i)'を呼び出すループの使用を含むKhaled Kの方法を使用してください。 –

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); 

あなたは間違っているだろう除き、それは2つの異なるオブジェクトごとに2つの参照を持っている、リストは現在4つのオブジェクトを持っていると思うかもしれませんが、簡単なテストはどのように表示されます。

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

また、コピーコンストラクタを持っていて、上にクローンを作成するオブジェクトを渡すことができます。

またあなたのオブジェクトクラスは、インターフェイス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 
} 
+0

'for(MyObj m:list)list.add(whatever);'は反復処理中にリストに追加するため、 'ConcurrentModificationException'をスローします。 –

+1

@KlitosKyriacou Thxがメモのために修正されました。 –

関連する問題