Eclipseコレクションの紹介

Eclipseコレクションの紹介

1. 概要

Eclipse Collectionsは、Java用に改良されたもう1つのコレクションフレームワークです。

簡単に言えば、コアJavaにはない追加のデータ構造と機能に加えて、最適化された実装を提供します。

このライブラリは、すべてのデータ構造の可変および不変の両方の実装を提供します。

2. メーベン依存

次のMaven依存関係をpom.xmlに追加することから始めましょう。

org.eclipse.collections
    eclipse-collections
    8.2.0

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

3. 大きな絵

3.1. 基本的なコレクションタイプ

Eclipseコレクションの基本的なコレクションタイプは次のとおりです。

  • ListIterable –挿入順序を維持し、要素の重複を許可する順序付きコレクション。 サブインターフェイスには、MutableListFixedSizeList、およびImmutableListが含まれます。 最も一般的なListIterable implementation is FastList, which is a subclass of MutableList

  • SetIterable –重複する要素を許可しないコレクション。 ソートまたはソート解除できます。 サブインターフェイスには次のものがあります。SortedSetIterableおよびUnsortedSetIterable.最も一般的なソートされていないSetIterableの実装はUnifiedSetです。

  • MapIterable –キーと値のペアのコレクション。 サブインターフェイスには、MutableMapFixedSizeMap、およびImmutableMapが含まれます。 2つの一般的な実装は、UnifiedMapMutableSortedMapです。 UnifiedMapは順序を維持しませんが、MutableSortedMapは要素の自然な順序を維持します

  • BiMap –どちらの方向にも反復できるキーと値のペアのコレクション。 BiMapMapIterableインターフェースを拡張します

  • Bag –重複を許可する順序付けられていないコレクション。 サブインターフェイスには、MutableBag andFixedSizeBagが含まれます。 最も一般的な実装はHashBagです

  • StackIterable –「後入れ先出し」の順序を維持し、要素を逆の挿入順序で反復するコレクション。 サブインターフェイスには、MutableStackImmutableStackが含まれます

  • MultiMap –キーごとに複数の値を許可するキーと値のペアのコレクション

3.2. プリミティブコレクション

The framework also provides a huge set of primitive collections;それらの実装は、それらが保持するタイプにちなんで名付けられています。 それらのタイプごとに、可変、不変、同期、および変更不可のフォームがあります。

  • プリミティブLists

  • プリミティブSets

  • プリミティブStacks

  • プリミティブBags

  • プリミティブMaps

  • IntInterval

プリミティブキーまたはオブジェクトキー、およびプリミティブ値またはオブジェクト値のすべての可能な組み合わせをカバーする膨大な数のプリミティブマップフォームがあります。

簡単な注意–IntIntervalは、ステップ値を使用して繰り返すことができる整数の範囲です。

4. コレクションのインスタンス化

ArrayListまたはHashSetに要素を追加するには、引数なしのコンストラクターを呼び出してコレクションをインスタンス化し、各要素を1つずつ追加します。

Eclipseコレクションでもそれを行うことができますが、we can also instantiate a collection and provide all initial elements at the same time in a single line.

FastListをインスタンス化する方法を見てみましょう。

MutableList list = FastList.newListWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");

同様に、UnifiedSetをインスタンス化し、要素をnewSetWith()静的メソッドに渡すことで要素を追加できます。

Set comparison = UnifiedSet.newSetWith(
  "Porsche", "Volkswagen", "Toyota", "Mercedes");

HashBagをインスタンス化する方法は次のとおりです。

MutableBag bag = HashBag.newBagWith(
  "Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");

マップをインスタンス化し、キーと値のペアをマップに追加することも同様です。 唯一の違いは、キーと値のペアをPairインターフェイスの実装としてnewMapWith()メソッドに渡すことです。

例としてUnifiedMapを取り上げましょう。

Pair pair1 = Tuples.pair(1, "One");
Pair pair2 = Tuples.pair(2, "Two");
Pair pair3 = Tuples.pair(3, "Three");

UnifiedMap map = new UnifiedMap<>(pair1, pair2, pair3);

Java Collections APIアプローチを引き続き使用できます。

UnifiedMap map = new UnifiedMap<>();

map.put(1, "one");
map.put(2, "two");
map.put(3, "three");

add()remove()などのimmutable collections cannot be modified, they do not have implementations of methods that modify collections以降。

ただし、変更できないコレクションを使用すると、これらのメソッドを呼び出すことができますが、呼び出すとUnsupportedOperationExceptionがスローされます。

5. コレクションからの要素の取得

標準のListsを使用するのと同じように、EclipseコレクションListsの要素はそれらのインデックスによって取得できます。

list.get(0);

また、Eclipse Collectionsマップの値は、キーを使用して取得できます。

map.get(0);

getFirst()メソッドとgetLast()メソッドを使用して、リストの最初と最後の要素をそれぞれ取得できます。 他のコレクションの場合、イテレーターによって返される最初と最後の要素を返します。

map.getFirst();
map.getLast();

メソッドmax()およびmin()を使用して、自然な順序に基づいてコレクションの最大値と最小値を取得できます。

map.max();
map.min();

6. コレクションを反復処理する

Eclipseコレクションは、コレクションを反復処理するための多くの方法を提供します。 それらが何であるか、そしてそれらが実際にどのように機能するかを見てみましょう。

6.1. コレクションのフィルタリング

選択パターンは、論理条件を満たすコレクションの要素を含む新しいコレクションを返します。 これは本質的にフィルタリング操作です。

例を示しましょう。

@Test
public void givenListwhenSelect_thenCorrect() {
    MutableList greaterThanThirty = list
      .select(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

同じことは、単純なラムダ式を使用して行うことができます。

return list.select(i -> i > 30)
  .sortThis();

拒否パターンは逆です。 論理条件を満たさないすべての要素のコレクションを返します。

例を見てみましょう:

@Test
public void whenReject_thenCorrect() {
    MutableList notGreaterThanThirty = list
      .reject(Predicates.greaterThan(30))
      .sortThis();

    Assertions.assertThat(notGreaterThanThirty)
      .containsExactlyElementsOf(this.expectedList);
}

ここでは、30を超えるすべての要素を拒否します。

6.2. collect()メソッド

collectメソッドは、提供されたラムダ式によって返される結果を要素とする新しいコレクションを返します。基本的には、Stream APIからのmap()collect()の組み合わせです。

実際の動作を見てみましょう。

@Test
public void whenCollect_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");

    MutableList students = FastList
      .newListWith(student1, student2);

    MutableList lastNames = students
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsExactly("Hopkins", "Adams");
}

作成されたコレクションlastNamesには、studentsリストから収集された名前が含まれています。

しかし、what if the returned collection is a collection of collections and we do not want to maintain a nested structure?

たとえば、各学生が複数の住所を持っていて、コレクションのコレクションではなくStringsとして住所を含むコレクションが必要な場合は、flatCollect()メソッドを使用できます。

例を示しましょう。

@Test
public void whenFlatCollect_thenCorrect() {
    MutableList addresses = students
      .flatCollect(Student::getAddresses);

    Assertions.assertThat(addresses)
      .containsExactlyElementsOf(this.expectedAddresses);
}

6.3. 元素検出

detectメソッドは、論理条件を満たす最初の要素を見つけて返します。

簡単な例を見てみましょう。

@Test
public void whenDetect_thenCorrect() {
    Integer result = list.detect(Predicates.greaterThan(30));

    Assertions.assertThat(result)
      .isEqualTo(41);
}

anySatisfyメソッドは、コレクションのいずれかの要素が論理条件を満たすかどうかを判別します。

例を示しましょう。

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.anySatisfy(Predicates.greaterThan(30));

    assertTrue(result);
}

同様に、allSatisfyメソッドは、コレクションのすべての要素が論理条件を満たすかどうかを判別します。

簡単な例を見てみましょう:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    boolean result = list.allSatisfy(Predicates.greaterThan(0));

    assertTrue(result);
}

6.4. partition()メソッド

partitionメソッドは、要素が論理条件を満たすかどうかに応じて、コレクションの各要素を2つのコレクションのいずれかに割り当てます。

例を見てみましょう:

@Test
public void whenAnySatisfiesCondition_thenCorrect() {
    MutableList numbers = list;
    PartitionMutableList partitionedFolks = numbers
      .partition(i -> i > 30);

    MutableList greaterThanThirty = partitionedFolks
      .getSelected()
      .sortThis();
    MutableList smallerThanThirty = partitionedFolks
      .getRejected()
      .sortThis();

    Assertions.assertThat(smallerThanThirty)
      .containsExactly(1, 5, 8, 17, 23);
    Assertions.assertThat(greaterThanThirty)
      .containsExactly(31, 38, 41);
}

6.5. 怠惰な反復

遅延反復は、反復メソッドが呼び出される最適化パターンですが、実際の実行は、アクションまたは戻り値が別の後続のメソッドで必要になるまで延期されます。

@Test
public void whenLazyIteration_thenCorrect() {
    Student student1 = new Student("John", "Hopkins");
    Student student2 = new Student("George", "Adams");
    Student student3 = new Student("Jennifer", "Rodriguez");

    MutableList students = Lists.mutable
      .with(student1, student2, student3);
    LazyIterable lazyStudents = students.asLazy();
    LazyIterable lastNames = lazyStudents
      .collect(Student::getLastName);

    Assertions.assertThat(lastNames)
      .containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez"));
}

ここで、lazyStudentsオブジェクトは、collect()メソッドが呼び出されるまで、studentsリストの要素を取得しません。

7. コレクション要素のペアリング

メソッドzip()は、2つのコレクションの要素をペアに結合することにより、新しいコレクションを返します。 2つのコレクションのいずれかが長い場合、残りの要素は切り捨てられます。

それをどのように使用できるか見てみましょう:

@Test
public void whenZip_thenCorrect() {
    MutableList numbers = Lists.mutable
      .with("1", "2", "3", "Ignored");
    MutableList cars = Lists.mutable
      .with("Porsche", "Volvo", "Toyota");
    MutableList> pairs = numbers.zip(cars);

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

zipWithIndex()メソッドを使用して、コレクションの要素をそれらのインデックスとペアにすることもできます。

@Test
public void whenZip_thenCorrect() {
    MutableList cars = FastList
      .newListWith("Porsche", "Volvo", "Toyota");
    MutableList> pairs = cars.zipWithIndex();

    Assertions.assertThat(pairs)
      .containsExactlyElementsOf(this.expectedPairs);
}

8. コレクションの変換

Eclipse Collectionsは、コンテナータイプを別のタイプに変換するための簡単なメソッドを提供します。 これらのメソッドは、toList()toSet()toBag()、およびtoMap().です。

それらをどのように使用できるか見てみましょう。

public static List convertToList() {
    UnifiedSet cars = new UnifiedSet<>();

    cars.add("Toyota");
    cars.add("Mercedes");
    cars.add("Volkswagen");

    return cars.toList();
}

テストを実行してみましょう:

@Test
public void whenConvertContainerToAnother_thenCorrect() {
    MutableList cars = (MutableList) ConvertContainerToAnother
      .convertToList();

    Assertions.assertThat(cars)
      .containsExactlyElementsOf(
      FastList.newListWith("Volkswagen", "Toyota", "Mercedes"));
}

9. 結論

このチュートリアルでは、Eclipseコレクションとそれらが提供する機能の概要を簡単に説明しました。

このチュートリアルの完全な実装は、over on GitHubで利用できます。