次は可能ですか?はいの場合、それには欠点がありますか、これを行うにはより良い方法がありますか?リストの要素をjavaの同じリストに追加
List<Integer> myList = new ArrayList<>();
myList.add(2);
myList.add(3);
// then add all the elements again
myList.add(myList);
次は可能ですか?はいの場合、それには欠点がありますか、これを行うにはより良い方法がありますか?リストの要素をjavaの同じリストに追加
List<Integer> myList = new ArrayList<>();
myList.add(2);
myList.add(3);
// then add all the elements again
myList.add(myList);
myList.add(myList);
との主な欠点は、myList
がInteger
ではないので、それは、コンパイルされませんということです。
あなたは、しかし、使用することができます。
myList.addAll(myList);
または
myList.addAll(new ArrayList<>(myList));
あなたが安全にそれをしたい場合。
myList.addAll(myList);
=>動作します。
myList.add(myList);
=>コンパイルされませんが、.addメソッドは、引数として整数(int型ではない)が必要で、あなたは別のリストを使用して呼び出すことはできません。
これはOracleの実装では機能しますが、API仕様で動作することは保証されていません(詳細は私の回答を参照してください) –
addAll
メソッドArrayList
は、OracleのJDK(およびOpenJDK)で動作します。しかし、それは保証されていません。 Javadoc for addAll
のコメント:
操作の進行中に指定されたコレクションが変更されると、この操作の動作は未定義です。指定されたコレクションがこのリストであり、このリストが空でない場合、この呼び出しの動作は未定義であることを意味します。この事例が証明するように、「試してみる」だけでは、何かが正しく動作するかどうかの十分なテストではありません。
実際、list.addAll(list)
が機能するかどうかを考えるとき、どのように実装されているのか自分に尋ねる必要があります。単純にlist
を繰り返して、各要素をlist
の末尾に追加すると、ConcurrentModificationException
(またはそれ以外の場合は無限ループになります)が表示されます。そのため、Javadocはそのような呼び出しが動作することを保証しません。 Oracleの実装は、渡されたリストを配列にコピーした後、配列の各要素をリストの最後にコピーします。つまり、リストのためにaddAll
を呼び出すと、余分なコピーを作成せずに自分で行うよりも効率的ではない可能性があります。
お勧めしますか? – daljit97
@ daljit97これを安全に行う方法を示す2つの回答のいずれか。 Andy Turnerは 'myList.addAll(new ArrayList <>(myList));'を表示します。これは簡潔であるという利点がありますが、Oracleの実装でも別のコピーが作成されても、 'myList'のコピーが作成されます。これはもっと読みやすいので、私の好む方法ですが、リストが非常に長く、余分なコピーを作成するのに十分なメモリがない場合は、 'get(i)'を呼び出すループの使用を含むKhaled Kの方法を使用してください。 –
基本データ型(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
}
'for(MyObj m:list)list.add(whatever);'は反復処理中にリストに追加するため、 'ConcurrentModificationException'をスローします。 –
@KlitosKyriacou Thxがメモのために修正されました。 –
試しましたか?試してみると、何かが可能かどうかをテストする最良の方法です。 – DyZ
実際には 'for'ループを使用して伝統的な方法で行うことができます –