Java - 複数のコレクションを組み合わせる

Java –複数のコレクションを組み合わせる

1. 概要

このチュートリアルでは、複数のコレクションを1つの論理コレクションに連結する方法を説明します。

5つの異なるアプローチを検討します。2つはJava 8を使用し、1つはGuavaを使用し、1つはApache Commons Collectionsを使用し、もう1つは標準Java 7 SDKのみを使用します。

次の例では、次のコレクションについて考えてみましょう。

Collection collectionA = asList("S", "T");
Collection collectionB = asList("U", "V");

2. Java 8StreamAPIの使用

Java APIのStreamインターフェースは、コレクションの処理を容易にする便利なメソッドを提供します。 コレクションの結合に使用される2つのメソッド(concat()flatMap())を見てみましょう。

Streamを取得すると、それに対して集計操作を実行できます。

2.1. concat()メソッドの使用__

静的メソッドconcat()は、要素が最初のStreamのすべての要素であり、その後に2番目のStreamのすべての要素が続く、遅延連結されたStreamを作成することにより、2つのStreamsを論理的に結合します。 t4)s。

以下の例では、concat()メソッドを使用してcollectionAcollectionBを組み合わせてみましょう。

Stream combinedStream = Stream.concat(
  collectionA.stream(),
  collectionB.stream());

3つ以上のStreamsを組み合わせる必要がある場合は、元の呼び出し内からconcat()メソッドを再度呼び出すことができます。

Stream combinedStream = Stream.concat(
  Stream.concat(collectionA.stream(), collectionB.stream()),
  collectionC.stream());

Java 8Streamsは再利用できないため、変数に割り当てる際にはこれを考慮に入れる必要があることに注意してください。

2.2. flatMap()メソッドの使用__

flatMap()メソッドは、このStreamの各要素を、提供されたマッピング関数を各要素に適用することによって生成されたマップされたStreamの内容で置き換えた後、Streamを返します。

以下の例は、flatMap()メソッドを使用したコレクションのマージを示しています。 最初に、要素が2つのコレクションであるStreamを取得し、次に、マージされたリストに収集する前にStreamをフラット化します。

Stream combinedStream = Stream.of(collectionA, collectionB)
  .flatMap(Collection::stream);
Collection collectionCombined =
  combinedStream.collect(Collectors.toList());

3. グアバの使用

GoogleのGuavaライブラリには、コレクションを操作するための便利なメソッドがいくつか用意されており、Java 6以降で使用できます。

3.1. Iterables.concat()メソッドの使用

Iterables.concat()メソッドは、コレクションのマージに使用されるGuavaの便利なメソッドの1つです。

Iterable combinedIterables = Iterables.unmodifiableIterable(
  Iterables.concat(collectionA, collectionA));

返されるIterableは、コレクションに変換できます。

Collection collectionCombined = Lists.newArrayList(combinedIterables);

3.2. メーベン依存

次の依存関係をMavenpom.xmlファイルに追加して、プロジェクトにGuavaライブラリを含めます。


    com.google.guava
    guava
    20.0

Guavaライブラリの最新バージョンはMaven Centralリポジトリにあります。

4. Apache Commonsコレクションの使用

Apache Commons Collectionsは、さまざまなコレクションの操作を支援するユーティリティのもう1つのライブラリです。 このライブラリは、コレクションの結合に使用できる2つのユーティリティメソッドを提供します。 このセクションでは、これらのメソッドがどのように機能するかを理解しましょう。

4.1. IterableUtils.chainedIterable()メソッドの使用

IterableUtilsクラスは、Iterableインスタンスのユーティリティメソッドとデコレータを提供します。 複数のIterableを1つに結合するために使用できるchainedIterable()メソッドを提供します。

Iterable combinedIterables = IterableUtils.chainedIterable(
  collectionA, collectionB);

4.2. CollectionUtils.union()メソッドの使用

Collectionインスタンスのユーティリティメソッドとデコレータは、CollectionUtilsクラスによって提供されます。 このクラスのunion()メソッドは、指定されたIterableインスタンスの和集合を含むCollectionを返します。

Iterable combinedIterables = CollectionUtils.union(
  collectionA, collectionB);

union()メソッドの場合、返されるコレクション内の各要素のカーディナリティは、指定された2つのIterables内のその要素のカーディナリティの最大値に等しくなります。 つまり、結合されたコレクションは、最初のコレクションの要素と、最初のコレクションには存在しなかった2番目のコレクションの要素のみで構成されます。

4.3. メーベン依存

次の依存関係をMavenpom.xmlファイルに追加して、プロジェクトにApache CommonsCollectionsライブラリを含めます。


    org.apache.commons
    commons-collections4
    4.1

Apache Commonsライブラリの最新バージョンは、Maven Centralリポジトリにあります。

5. Java 7を使用する

まだJava7を使用していて、Guavaなどのサードパーティライブラリを避けたい場合は、addAll()メソッドを使用して複数のコレクションの要素を結合するか、独自のユーティリティメソッドを記述してIterablesを結合できます。 。

5.1. addAll()メソッドの使用

もちろん、コレクションを組み合わせる最も簡単な解決策は、次のListの例のように、addAll()メソッドを使用することですが、このメソッドは、同じオブジェクトへの追加の参照を含む新しいコレクションを作成することに注意してください。最初の2つのコレクション:

List listC = new ArrayList<>();
listC.addAll(listA);
listC.addAll(listB);

5.2. カスタムconcat()メソッドの記述

次の例では、2つのIterablesを受け入れ、マージされたIterableオブジェクトを返すconcat()メソッドを定義しています。

public static  Iterable concat(
  Iterable i1,
  Iterable i2) {
        return new Iterable() {
            public Iterator iterator() {
                return new Iterator() {
                    Iterator listIterator = i1.iterator();
                    Boolean checkedHasNext;
                    E nextValue;
                    private boolean startTheSecond;

                    void theNext() {
                        if (listIterator.hasNext()) {
                            checkedHasNext = true;
                            nextValue = listIterator.next();
                        } else if (startTheSecond)
                            checkedHasNext = false;
                        else {
                            startTheSecond = true;
                            listIterator = i2.iterator();
                            theNext();
                        }
                    }

                    public boolean hasNext() {
                        if (checkedHasNext == null)
                            theNext();
                        return checkedHasNext;
                    }

                    public E next() {
                        if (!hasNext())
                            throw new NoSuchElementException();
                        checkedHasNext = null;
                        return nextValue;
                    }

                    public void remove() {
                        listIterator.remove();
                    }
                };
            }
        };
    }

concat()メソッドは、2つのコレクションを引数として渡すことで呼び出すことができます。

Iterable combinedIterables = concat(collectionA, collectionB);
Collection collectionCombined = makeListFromIterable(combinedIterables);

IterableListとして使用できるようにする必要がある場合は、Iterableのメンバーを使用してListを作成するmakeListFromIterable()メソッドを使用することもできます。

public static  List makeListFromIterable(Iterable iter) {
    List list = new ArrayList();
    for (E item : iter) {
        list.add(item);
    }
    return list;
}

6. 結論

この記事では、2つのコレクションに含まれるオブジェクトへの追加の参照を作成せずに、Javaで2つのコレクションを論理的に組み合わせるいくつかの異なる方法について説明しました。

このチュートリアルのコードはover on Githubで入手できます。