JavaでコレクションをArrayListに変換する

JavaでコレクションをArrayListに変換する

1. 概要

Javaコレクションをあるタイプから別のタイプに変換することは、一般的なプログラミングタスクです。 このチュートリアルでは、任意のタイプのCollectionArrayListに変換します。

チュートリアル全体を通して、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);
    }
}

ここでは、フィールドidnameintStringであることがわかります。 これらのデータ型は値によってコピーされます。 したがって、単純に両方を割り当てることができます。

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 streamFooオブジェクトを名前で並べ替えるには:

ArrayList newList = srcCollection.stream()
  .sorted(Comparator.comparing(Foo::getName))
  .collect(toCollection(ArrayList::new));

河川次数の詳細については、このearlier tutorialをご覧ください。

7. 結論

ArrayListコンストラクターは、Collectionの内容を新しいArrayListに取り込むための効果的な方法です。

ただし、結果のリストを微調整する必要がある場合、Streams APIはプロセスを変更する強力な方法を提供します。

この記事で使用されているコードは、全体がover on GitHubにあります。