JavaでコレクションをArrayListに変換する
1. 概要
Javaコレクションをあるタイプから別のタイプに変換することは、一般的なプログラミングタスクです。 このチュートリアルでは、任意のタイプのCollectionをArrayListに変換します。
チュートリアル全体を通して、Fooオブジェクトのコレクションがすでにあると想定します。 そこから、さまざまなアプローチを使用してArrayList を作成します。
2. 例の定義
ただし、続行する前に、入力と出力をモデル化しましょう。
ソースは任意のタイプのコレクションである可能性があるため、Collectionインターフェースを使用して宣言します。
Collection srcCollection;
同じ要素タイプでArrayListを生成する必要があります。
ArrayList newList;
3. ArrayListコンストラクターの使用
コレクションを新しいコレクションにコピーする最も簡単な方法は、そのコンストラクターを使用することです。
以前のguide to ArrayListで、ArrayListコンストラクタがコレクションパラメータを受け入れることができることを学びました。
ArrayList newList = new ArrayList<>(srcCollection);
-
新しいArrayListには、ソースコレクション内のFoo要素の浅いコピーが含まれています。
-
順序は、ソースコレクションの順序と同じです。
コンストラクターは単純なので、ほとんどのシナリオで優れたオプションになります。
4. StreamsAPIの使用
さて、let’s take advantage of the Streams API to create an ArrayList from an existing Collection:_ _
ArrayList newList = srcCollection.stream().collect(toCollection(ArrayList::new));
このスニペットでは:
-
ソースコレクションからストリームを取得し、collect()演算子を適用してListを作成します
-
必要なリストタイプを取得するためにArrayList::newを指定します
-
このコードは、浅いコピーも作成します。
正確なListタイプを気にしない場合は、次のように簡略化できます。
List newList = srcCollection.stream().collect(toList());
toCollection()とtoList()はCollectorsから静的にインポートされることに注意してください。 詳細については、guide on Java 8’s Collectorsを参照してください。
5. ディープコピー
「浅いコピー」について言及する前に。 つまり、ソースコレクションにまだ存在するthe elements in the new list are exactly the same Foo instancesを意味します。 したがって、参照によりFoosをnewListにコピーしました。
modification will be reflected in both collectionsのいずれかのコレクション内のFooインスタンスの内容を変更した場合。 したがって、どちらかのコレクションwithoutの要素を変更してもう一方を変更する場合は、「ディープコピー」を実行する必要があります。
Fooをディープコピーするには、create a completely new Foo instance for each elementを使用します。 したがって、すべてのFooフィールドを新しいインスタンスにコピーする必要があります。
Fooクラスを定義して、それ自体をディープコピーする方法を認識できるようにします。
public class Foo {
private int id;
private String name;
private Foo parent;
public Foo(int id, String name, Foo parent) {
this.id = id;
this.name = name;
this.parent = parent;
}
public Foo deepCopy() {
return new Foo(
this.id, this.name, this.parent != null ? this.parent.deepCopy() : null);
}
}
ここでは、フィールドidとnameがintとStringであることがわかります。 これらのデータ型は値によってコピーされます。 したがって、単純に両方を割り当てることができます。
parentフィールドは、クラスである別のFooです。 Foo gotが変更された場合、その参照を共有するコードはすべて、これらの変更の影響を受けます。 We have to deep copy the parent field。
これで、ArrayListの変換に戻ることができます。 フローへのWe just need the map operator to insert the deep copy:
ArrayList newList = srcCollection.stream()
.map(foo -> foo.deepCopy())
.collect(toCollection(ArrayList::new));
どちらかのコレクションの内容を、もう一方に影響を与えることなく変更できます。
ディープコピーは、要素の数とデータの深さによっては時間がかかる場合があります。 ここで並列ストリームを使用すると、必要に応じてパフォーマンスが向上する場合があります。
6. リストの順序の制御
デフォルトでは、ストリームは、ソースコレクションで検出されたのと同じ順序で要素をArrayListに配信します。
その順序を変更したい場合はwe could apply the sorted() operator to the stream。 Fooオブジェクトを名前で並べ替えるには:
ArrayList newList = srcCollection.stream()
.sorted(Comparator.comparing(Foo::getName))
.collect(toCollection(ArrayList::new));
河川次数の詳細については、このearlier tutorialをご覧ください。
7. 結論
ArrayListコンストラクターは、Collectionの内容を新しいArrayListに取り込むための効果的な方法です。
ただし、結果のリストを微調整する必要がある場合、Streams APIはプロセスを変更する強力な方法を提供します。
この記事で使用されているコードは、全体がover on GitHubにあります。