リストをJavaの別のリストにコピーする

1.概要

このクイックチュートリアルでは、 List を別の List にコピーするさまざまな方法と、その過程で発生する一般的なエラーについて説明します。

Collections の使用法については、https://www.baeldung.com/java-collectionsを参照してください。

2.コンストラクタ

List をコピーする簡単な方法は、コレクションを引数としてとるコンストラクタを使用することです。

List<Plant> copy = new ArrayList<>(list);
  • ここでは参照をコピーしてオブジェクトを複製しないため、1つの要素で行われたすべての修正が両方のリストに影響します。**

そのため、コンストラクタを使用することは、不変オブジェクトをコピーするのに適しています。

List<Integer> copy = new ArrayList<>(list);

Integer は不変クラスです。その値はインスタンスの作成時に設定され、変更されることはありません。

したがって、 Integer 参照は複数のリストやスレッドで共有することができ、誰もその値を変更することはできません。

3. List ConcurrentAccessException

  • リストを扱う際の一般的な問題は ConcurrentAccessException です。** これは、リストをコピーしようとしている間にリストを変更していることを意味します。おそらく別のスレッドで実行されます。

この問題を解決するには、次のいずれかを実行する必要があります。

  • 同時アクセス収集用に設計されたものを使用する

  • コレクションを適切にロックして繰り返します。

  • 元のコレクションをコピーする必要がないようにする方法を見つける

私たちの最後のアプローチを考えると、それはスレッドセーフではありません。そのため、最初のオプションで問題を解決したい場合は、 CopyOnWhiteArrayList を使用することをお勧めします。ここでは、基礎となる配列の新しいコピーを作成することによってすべての変更操作を実装します。

詳細については、https://www.baeldung.com/java-copy-on-write-arraylist[この記事へ]を参照してください。

Collection をロックする場合は、 ReentrantReadWriteLock のように、ロック/プリミティブを使用して読み取り/書き込みアクセスをシリアル化することができます。

4. AddAll

要素をコピーするもう1つの方法は、 addAll メソッドを使用することです。

List<Integer> copy = new ArrayList<>();
copy.addAll(list);
  • このメソッドを使用するときは常に注意してください。コンストラクタと同様に、両方のリストの内容は同じオブジェクトを参照します。**

5. Collections.copy

Collections クラスは、コレクションを操作したりコレクションを返す静的メソッドだけで構成されています。

そのうちの1つは copy です。これには、少なくともソースと同じ長さのソースリストと宛先リストが必要です。

コピーされた各要素のインデックスを、オリジナルのようなコピー先リストに保持します。

List<Integer> source = Arrays.asList(1,2,3);
List<Integer> dest = Arrays.asList(4,5,6);
Collections.copy(dest, source);

上記の例では、両方のリストのサイズが同じであるため、 dest リストの前の要素はすべて上書きされています。

宛先リストのサイズがソースよりも大きい場合

List<Integer> source = Arrays.asList(1, 2, 3);
List<Integer> dest = Arrays.asList(5, 6, 7, 8, 9, 10);
Collections.copy(dest, source);

最初の3つの項目だけが上書きされ、リスト内の残りの要素は保存されます。

6. Java 8を使う

このバージョンのJavaは新しいツールを追加することによって私たちの可能性を開きます。次の例で検討するのは Stream です。

List<String> copy = list.stream()
  .collect(Collectors.toList());

この方法の主な利点は、スキップとフィルタを使用する機会です。次の例では、最初の要素をスキップします。

List<String> copy = list.stream()
  .skip(1)
  .collect(Collectors.toList());

String の長さでフィルタリングしたり、オブジェクトの属性を比較してフィルタリングすることもできます。

List<String> copy = list.stream()
  .filter(s -> s.length() > 10)
  .collect(Collectors.toList());
List<Flower> flowers = list.stream()
  .filter(f -> f.getPetals() > 6)
  .collect(Collectors.toList());

私たちがnull-safeな方法で仕事をしたいと思う可能性があります。

List<Flower> flowers = Optional.ofNullable(list)
  .map(List::stream)
  .orElseGet(Stream::empty)
  .collect(Collectors.toList());

この方法でも要素をスキップします。

List<Flower> flowers = Optional.ofNullable(list)
  .map(List::stream).orElseGet(Stream::empty)
  .skip(1)
  .collect(Collectors.toList());

7. Java 10を使う

最後に、最新のJavaバージョンの1つでは、指定された Collectionの要素を含む不変の List__を作成できます。

List<T> copy = List.copyOf(list);

唯一の条件は、与えられたCollectionがnullである必要はなく、null要素を含んではいけないということです。

8.まとめ

この記事では、 Java のバージョンが異なる別の List List をコピーするさまざまな方法と、その過程で発生する一般的なエラーについて説明しました。

いつものように、コードサンプルはGitHub here およびhttps://github.com/eugenp/tutorials/tree/にあります。 master/core-java-10[ここ]。

前の投稿:RxJavaでの観測量の組み合わせ
次の投稿:2016年3月のJava 8採用