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


135

私が持っているList<SomeBean>Webサービスから移入されました。そのリストの内容を同じタイプの空のリストにコピー/クローンしたいのですが。リストをコピーするためのグーグル検索は私に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後でコードを取得しました。ヒットアンドトライアル。:)

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


11
もちろんコピーはイテレーションを使用します。あなたはそれを隠すことができますが、それはまだそこにあります。
Peter Lawrey

1
まず、そのリストをコピーする必要がありますか?それをする動機は?
ppeterka 2013年

2
うん、イテレーションはそのレイヤーの下に隠されています。しかし、コメントは反復の回答を防ぐために追加されました。:)
Mono Jamoon 2013年

@ppeterka removeAll()のように、リストに対して操作を実行しています。これにより、リストの元のデータが失われます。あとは「あのデータ」も必要です。
Mono Jamoon 2013年

によって返されているリストの実際のタイプは何app.allInOne(template)ですか?ArrayList
Andremoniy

回答:


235

これを使うだけです:

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

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


1
今、私は本当に愚かだと思います:)このように構築しても何も投げられないことを願っていますConcurrentAccessException
Mono Jamoon 2013年


5
+1彼がConcurrentModifcationExceptionを取得している場合、最初に修正する必要がある同時実行性の問題があります。
Peter Lawrey

5
質問に「コピー/クローン」と記載されているのに、なぜこの回答が非常に多くのポイントを獲得するのですか?これは、他のいくつかの回答がクローン作成と関係がない場合に限ります。使用するコレクション/ストリーム固有のユーティリティメソッドに関係なく、コレクション内のオブジェクトには同じ参照が保持されます。
yuranos

3
答えは間違っています。コンテンツはコピーされません。参照のみです。
1

33

これは、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());

4
結果のリストは、元のリストの深いコピーですか、それとも浅いコピーですか?
Ad Infininitum

7
浅いコピー。
2016年

3
残念ながら、これもスレッドセーフではありません。listコレクターの実行中に変更されたと仮定すると、ConcurrentModificationExceptionがスローされます。
C-Otto

@ダン、最後の要素のコピーをスキップするには?
CKM 2017年

@chandresh最後の要素のコピーをスキップするには、次のように使用します.limit(list1.size() - 1)
Matthew Carpenter

13
originalArrayList.addAll(copyArrayofList);

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

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


2
これは、#addAllが浅いコピーを作成すること、およびディープコピーの方法を指定するため、ここで数少ない真の回答の1つです。詳細: stackoverflow.com/questions/715650/...
cellepo

7

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

ConcurrentAccessExceptionが発生しました

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

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

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

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


4

始まってJavaの10

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

List.copyOf()List指定されたの要素を含む変更不可能なものを返しますCollection

指定されたCollectionはであってはnullならず、null要素を含んではいけません。

また、の詳細なコピーを作成する場合は、ここでList多くの良い答えを見つけることができます。


3

nullセーフな方法でJava 8を使用する別のメソッドがあります。

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

1つの要素をスキップする場合。

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

Java 9+では、オプションのストリームメソッドを使用できます

Optional.ofNullable(wsList)
    .stream()
    .flatMap(Collection::stream)
    .collect(Collectors.toList())

1

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

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

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

したがって、一度に1つの操作のみが機能し、例外を回避します...


1

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

1)Collections.copy(destList、sourceList)の実装は、まずsize()メソッドを呼び出して宛先リストのサイズを確認します。size()メソッドの呼び出しは常にリスト内の要素の数(この場合は0)を返すため、コンストラクターArrayList(capacity)は、バッキング配列の初期容量のみを保証し、これは、リストのサイズ。したがって、常にIndexOutOfBoundsExceptionを取得します。

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

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

0

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




-2

あるリストでの変更が別のリストに影響を与えたくない場合は、これを試してみてください

  public class MainClass {
  public static void main(String[] a) {

    List list = new ArrayList();
    list.add("A");

    List list2 = ((List) ((ArrayList) list).clone());

    System.out.println(list);
    System.out.println(list2);

    list.clear();

    System.out.println(list);
    System.out.println(list2);
  }
}

> Output:   
[A]  
[A]  
[]  
[A]

-3

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.