Javaでリストを別のリストにコピーする
1. 概要
このクイックチュートリアルでは、Listを別のListにコピーするさまざまな方法と、その過程で発生する一般的なエラーを示します。
Collectionsの使用の概要については、to this article hereを参照してください。
2. コンストラクタ
Listをコピーする簡単な方法は、コレクションを引数として取るコンストラクターを使用することです。
List copy = new ArrayList<>(list);
ここでは参照をコピーしており、オブジェクトのクローンを作成していないため、1つの要素で行われたすべての修正は、両方のリストに影響します。
そのため、コンストラクターを使用すると、不変オブジェクトをコピーできます。
List copy = new ArrayList<>(list);
Integerは不変のクラスであり、その値はインスタンスの作成時に設定され、変更することはできません。
したがって、Integer参照は複数のリストとスレッドで共有でき、誰もその値を変更することはできません。
3. ListConcurrentAccessException
A common problem working with lists is the ConcurrentAccessException.これは、リストをコピーしようとしているときに、おそらく別のスレッドでリストを変更していることを意味している可能性があります。
この問題を解決するには、次のいずれかを行う必要があります。
-
同時アクセスコレクション用に設計された
-
コレクションを適切にロックして反復処理する
-
元のコレクションをコピーする必要がないようにする方法を見つける
最後のアプローチを考えると、スレッドセーフではありません。 したがって、最初のオプションで問題を解決したい場合は、CopyOnWhiteArrayListを使用することをお勧めします。この場合、基になる配列の新しいコピーを作成することにより、すべての変更操作が実装されます。
詳細については、to this articleを参照してください。
Collectionをロックする場合は、ロックプリミティブを使用して、ReentrantReadWriteLockなどの読み取り/書き込みアクセスをシリアル化することができます。
4. AddAll
要素をコピーする別のアプローチは、addAllメソッドを使用することです。
List copy = new ArrayList<>();
copy.addAll(list);
このメソッドを使用するときは常に、コンストラクターと同様に、両方のリストのコンテンツが同じオブジェクトを参照することを覚えておくことが重要です。
5. Collections.copy
Collectionsクラスは、コレクションを操作または返す静的メソッドのみで構成されます。
そのうちの1つはcopyで、少なくともソースと同じ長さのソースリストと宛先リストが必要です。
オリジナルのような宛先リスト内のコピーされた各要素のインデックスを維持します:
List source = Arrays.asList(1,2,3);
List dest = Arrays.asList(4,5,6);
Collections.copy(dest, source);
上記の例では、両方のリストのサイズが同じであるため、destリストの以前のすべての要素が上書きされました。
宛先リストのサイズがソースよりも大きい場合:
List source = Arrays.asList(1, 2, 3);
List dest = Arrays.asList(5, 6, 7, 8, 9, 10);
Collections.copy(dest, source);
最初の3つの項目のみが上書きされ、リスト内の残りの要素は保存されます。
6. Java 8の使い方
このバージョンのJavaは、新しいツールを追加することで可能性を開きます。 次の例で検討するのはStreamです。
List copy = list.stream()
.collect(Collectors.toList());
この方法の主な利点は、スキップとフィルターを使用できることです。 次の例では、最初の要素をスキップします。
List copy = list.stream()
.skip(1)
.collect(Collectors.toList());
Stringの長さでフィルタリングすることも、オブジェクトの属性を比較することでフィルタリングすることもできます。
List copy = list.stream()
.filter(s -> s.length() > 10)
.collect(Collectors.toList());
List flowers = list.stream()
.filter(f -> f.getPetals() > 6)
.collect(Collectors.toList());
ヌルセーフな方法で作業したい可能性があります。
List flowers = Optional.ofNullable(list)
.map(List::stream)
.orElseGet(Stream::empty)
.collect(Collectors.toList());
また、この方法を使用して要素をスキップします。
List flowers = Optional.ofNullable(list)
.map(List::stream).orElseGet(Stream::empty)
.skip(1)
.collect(Collectors.toList());
7. Java 10の使用
最後に、最後のJavaバージョンの1つを使用すると、指定されたCollection:の要素を含む不変のListを作成できます。
List copy = List.copyOf(list);
唯一の条件は、指定されたコレクションがnullであってはならず、null要素が含まれていてはならないということです。