159

List<SomeBean>Web サービスから取り込まれた があります。そのリストの内容を同じタイプの空のリストにコピー/クローンしたい。リストをコピーするための Google 検索で、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ヒットアンドトライアル。:)

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

4

14 に答える 14

268

これを使用するだけです:

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

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

于 2013-01-14T13:53:44.687 に答える
37

これは、それを行うための非常に優れた 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());
于 2015-12-10T12:36:50.617 に答える
7

このようなことをしようとしましたが、それでも IndexOutOfBoundsException が発生しました。

ConcurrentAccessException が発生しました

これは、おそらく別のスレッドでリストをコピーしようとしているときにリストを変更していることを意味します。これを修正するには、次のいずれかを行う必要があります

  • 同時アクセス用に設計されたコレクションを使用します。

  • コレクションを適切にロックして、反復処理できるようにします (または、これを行うメソッドを呼び出せるようにします)。

  • 元のリストをコピーする必要がないように、離れた場所を見つけてください。

于 2013-01-14T13:58:36.667 に答える
1

同様のことを試してみたところ、問題を再現できました(IndexOutOfBoundsException)。以下は私の発見です:

1) Collections.copy(destList, sourceList) の実装は、最初に size() メソッドを呼び出して宛先リストのサイズをチェックします。size() メソッドの呼び出しは常にリスト内の要素数 (この場合は 0) を返すため、コンストラクター ArrayList(capacity) はバッキング配列の初期容量のみを保証し、これは配列とは何の関係もありません。リストのサイズ。したがって、常に IndexOutOfBoundsException が発生します。

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

List<SomeBean> wsListCopy=new ArrayList<SomeBean>(wsList);  
于 2013-01-14T19:54:45.740 に答える
1

私は同じ問題ConcurrentAccessExceptionを抱えていましたが、私の解決策は次のとおりでした:

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

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

そのため、一度に 1 つの操作のみが機能し、例外を回避できます...

于 2015-10-16T04:24:51.107 に答える
1

addAll() を使用できます。

例:wsListCopy.addAll(wsList);

于 2018-01-03T04:30:56.383 に答える
0

re: indexOutOfBoundsException、サブリストの引数が問題です。サブリストは size-1 で終了する必要があります。ゼロから始まるため、リストの最後の要素は常にサイズ 1 であり、サイズの位置に要素がないため、エラーが発生します。

于 2013-10-10T17:51:23.823 に答える
-3

subList 関数はトリックです。返されたオブジェクトは元のリストのままです。したがって、subList で何らかの操作を行うと、シングル スレッドかマルチ スレッドかに関係なく、コードで同時例外が発生します。

于 2015-06-04T14:20:36.243 に答える