web-dev-qa-db-ja.com

Java.util.Listを別のJava.util.Listにコピーする方法

私はWebサービスから移入されたList<SomeBean>を持っています。そのリストの内容を同じタイプの空のリストにコピー/複製したいです。リストをコピーするためのグーグル検索は私にCollections.copy()メソッドを使うことを勧めました。私が見たすべての例では、コピー先のリストには、コピーを実行するための正確な数の項目が含まれているはずです。

私が使用しているリストはWebサービスを介して生成され、それは何百ものオブジェクトを含んでいるので、私は上記のテクニックを使用することはできません。それとも間違って使っていますか?とにかく、それを機能させるために、私はこのようなことをやろうとしました、しかし、私はまだIndexOutOfBoundsExceptionを得ました。

List<SomeBean> wsList = app.allInOne(template);

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList.size());   
Collections.copy(wsListCopy,wsList);
System.out.println(wsListCopy.size());

wsListCopy=wsList.subList(0, wsList.size())を使用しようとしましたが、コードの後半でConcurrentAccessExceptionを取得しました。ヒットして試用します。 :)

とにかく、私の質問は簡単です私のリストの全内容を別のリストにコピーするにはどうすればいいですか?もちろん、繰り返しではありません。

119
Mono Jamoon

これを使うだけです:

List<SomeBean> newList = new ArrayList<SomeBean>(otherList);

注:それでも、スレッドセーフではありません。otherListを別のスレッドから変更した場合は、そのotherList(さらにnewList)を CopyOnWriteArrayList にするか、または次のようなロックプリミティブを使用します。 ReentrantReadWriteLock 同時にアクセスされるリストへの読み取り/書き込みアクセスをシリアル化します。

216
fge

これは本当にいいJava 8の方法です:

List<String> list2 = list1.stream().collect(Collectors.toList());

もちろん、ここでの利点は、リストの一部のみをフィルタリングしてスキップできることです。

例えば.

//don't copy the first element 
List<String> list2 = list1.stream().skip(1).collect(Collectors.toList());
27
Dan
originalArrayList.addAll(copyArrayofList);

コピーにaddAll()メソッドを使用する場合は常に注意してください。同じオブジェクトへの両方の配列リスト(originalArrayListとcopyArrayofList)の参照の内容がリストに追加されるため、いずれかを変更した場合そのうちcopyArrayofListも同じ変更を反映します。

副作用が必要ない場合は、forループまたはwhileループを使用して、originalArrayListからcopyArrayofListに各要素をコピーする必要があります。

11

私はこのようなことをやろうとしました、しかし私はまだIndexOutOfBoundsExceptionを得ました。

ConcurrentAccessExceptionが発生しました

これは、リストをコピーしようとしている間に、おそらく別のスレッドでリストを変更していることを意味します。これを直すにはどちらかの方法があります

  • 同時アクセス用に設計されたコレクションを使用してください。

  • コレクションを適切にロックして、それを繰り返すことができるようにします(または、これを実行するメソッドを呼び出すことができるようにします)。

  • 元のリストをコピーする必要がないようにするための方法を見つけます。

7
Peter Lawrey

Java 10以降

List<E> oldList = List.of();
List<E> newList = List.copyOf(oldList);

List.copyOf() は、与えられたListの要素を含む変更不可能なCollectionを返します。

与えられたCollectionnullであってはならず、またnull要素を含んではいけません。

また、Listのディープコピーを作成したい場合は、たくさんの良い答えを見つけることができます ここ

3
Oleksandr

Java 8にはもう1つ、null-safeな方法があります。

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
                                    .map(List::stream)
                                    .orElseGet(Stream::empty)
                                    .collect(Collectors.toList());

1要素スキップしたい場合.

List<SomeBean> wsListCopy = Optional.ofNullable(wsList)
                                    .map(List::stream)
                                    .orElseGet(Stream::empty)
                                    .skip(1)
                                    .collect(Collectors.toList());
3

私は同じ問題を抱えていましたConcurrentAccessExceptionそしてmysolutionは次のようになりました:

List<SomeBean> tempList = new ArrayList<>();

for (CartItem item : prodList) {
  tempList.add(item);
}
prodList.clear();
prodList = new ArrayList<>(tempList);

そのため、一度に1つの操作しか動作せず、実行は回避されます。

1
T04435

私は似たようなことを試してみて、問題を再現することができました(IndexOutOfBoundsException)。以下が私の調査結果です。

1)Collections.copy(destList、sourceList)の実装は、最初にsize()メソッドを呼び出して宛先リストのサイズをチェックします。 size()メソッドの呼び出しは常にリスト内の要素数(この場合は0)を返すので、コンストラクタArrayList(capacity)は補助配列の初期容量のみを保証します。リストのサイズしたがって、常にIndexOutOfBoundsExceptionが発生します。

2)比較的簡単な方法は、コレクションを引数とするコンストラクタを使用することです。

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  
1
Abhay Yadav

あなたはaddAll()を使うことができます。

例:wsListCopy.addAll(wsList);

0

indexOutOfBoundsExceptionに関しては、サブリストのargsが問題です。サブリストはサイズ1で終了する必要があります。ゼロベースであるため、リストの最後の要素は常にsize-1です。サイズ位置に要素がないため、エラーになります。

0
Jon Nelson

正解は見当たりません。ディープコピーが必要な場合は、オブジェクトを手動で繰り返しコピーする必要があります(コピーコンストラクタを使用できます)。

0