1概要

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

Java 8を使用する方法、Guavaを使用する方法、Apache Commons Collectionsを使用する方法、および標準のJava 7 SDKのみを使用する方法の5つの方法を検討します。

以下の例では、次のコレクションを考えてみましょう。

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


2 Java 8

Stream

API

の使用

Java APIの

Stream

インタフェースは、コレクションの処理を容易にする便利なメソッドを提供します。コレクションを組み合わせるために使用される2つのメソッド、

concat()



flatMap()

を見てみましょう。


Stream

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

** 2.1.

concat()

メソッドを使う+


__

**

静的メソッド

concat()

は、要素が最初の

Stream

のすべての要素で、その後に2番目の

Stream

のすべての要素が続く遅延連結された

Stream

を作成することによって、2つの

Streams

を論理的に結合します。

次の例では、

concat()

メソッドを使用して

collectionA



collectionB

を組み合わせてみましょう。

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

3つ以上の

Streams

を組み合わせる必要がある場合は、元の呼び出し内から

concat()

メソッドを再度呼び出すことができます。

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

Java 8

Streams

は再利用できないことに注意することが重要です。したがって、それらを変数に割り当てるときには、このことを考慮に入れる必要があります。

** 2.2.

flatMap()

メソッドを使う


__

**


flatMap()

メソッドは、この

Stream

の各要素を、提供されたマッピング関数を各要素に適用することによって生成されたmapped

Stream

の内容に置き換えた後で

Stream

を返します。

以下の例は、

flatMap()

メソッドを使用してコレクションをマージする方法を示しています。最初に、2つのコレクションを要素とする

Stream

を取得し、それをマージリストにまとめる前に

Stream

をフラット化します。

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


3 Guava

を使う

GoogleのGuavaライブラリは、コレクションを操作するための便利な方法をいくつか提供しており、Java 6以降で使用できます。


3.1.

Iterables.concat()

メソッドを使用する


Iterables.concat()

メソッドは、コレクションをマージするために使用されるGuavaの便利なメソッドの1つです。

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

返される

Iterable

はコレクションに変換できます。

Collection<String> collectionCombined = Lists.newArrayList(combinedIterables);


3.2. Mavenの依存関係

プロジェクトにGuavaライブラリを含めるには、Maven

pom.xml

ファイルに次の依存関係を追加します。

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>20.0</version>
</dependency>

最新バージョンのGuavaライブラリはhttps://search.maven.org/classic/#search%7Cga%7C1%7Cg%3A%22com.google.guava%22%20AND%20a%3A%22guavaにあります。 %22[Maven Central]リポジトリ。

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

**

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


4.1.

IterableUtils.chainedIterable()

メソッドを使用する


IterableUtils

クラスは、

Iterable

インスタンス用のユーティリティメソッドとデコレータを提供します。これは

chainedIterable()

メソッドを提供します。

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


4.2.

CollectionUtils.union()

メソッドの使用方法


Collection

インスタンスのユーティリティメソッドとデコレータは、

CollectionUtils

クラスによって提供されます。このクラスの

union()メソッドは、指定された

Iterable

インスタンスの和集合を含む

Collection__を返します。

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


union()メソッドの場合、返されるコレクション内の各要素の濃度は、指定された2つの

Iterables内のその要素の濃度の最大値に等しくなります。つまり、結合コレクションは、最初のコレクションに含まれていなかった最初のコレクションの要素と2番目のコレクションの要素のみで構成されます。


4.3. Mavenの依存関係

プロジェクトにApache Commons Collectionsライブラリを含めるには、Maven

pom.xml

ファイルに次の依存関係を追加します。

<dependency>
    <groupId>org.apache.commons</groupId>
    <artifactId>commons-collections4</artifactId>
    <version>4.1</version>
</dependency>

Apache Commonsライブラリの最新版はhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22commons-collections4%22[Maven Central]リポジトリにあります。


5 Java 7

を使う

まだJava 7を使用していて、Guavaのようなサードパーティのライブラリを避けたい場合は、

addAll()

メソッドを使用して複数のコレクションからの要素を結合するか、独自のユーティリティメソッドを作成して

Iterables

を結合できます。


5.1.

addAll()

メソッドを使用する

もちろん、コレクションを組み合わせるための最も簡単な解決策は、次の

List

の例のように

addAll()

メソッドを使用することですが、このメソッドが最初の2つのコレクションにあるものと同じオブジェクトへの追加参照を持つ新しいコレクションを作成することに注意してください。 :

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


5.2. カスタム

concat()

メソッドを書く

次の例では、2つの

Iterables

を受け入れてマージされた

Iterable

オブジェクトを返す

concat()

メソッドを定義しています。

public static <E> Iterable<E> concat(
  Iterable<? extends E> i1,
  Iterable<? extends E> i2) {
        return new Iterable<E>() {
            public Iterator<E> iterator() {
                return new Iterator<E>() {
                    Iterator<? extends E> 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<String> combinedIterables = concat(collectionA, collectionB);
Collection<String> collectionCombined = makeListFromIterable(combinedIterables);


Iterable



List

として使用可能にする必要がある場合は、

Iterable

のメンバーを使用して

List

を作成する

makeListFromIterable()

メソッドも使用できます。

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


6. 結論

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

このチュートリアルのコードはhttps://github.com/eugenp/tutorials/tree/master/core-java-collections[over on Github]から入手できます。