1. 概要

この記事では、永続的で不変のコレクションを提供するJavaライブラリであるPCollectionsについて説明します。

永続データ構造(コレクション)は、更新操作中に直接変更することはできません。更新操作の結果を含む新しいオブジェクトが返されます。 それらは不変であるだけでなく永続的でもあります。つまり、変更が実行された後、コレクションの以前のバージョンは変更されません。

PCollectionsは、Javaコレクションフレームワークに類似しており、互換性があります。

2. 依存関係

プロジェクトでPCollectionsを使用できるように、pom.xmlに次の依存関係を追加しましょう。

<dependency>
    <groupId>org.pcollections</groupId>
    <artifactId>pcollections</artifactId>
    <version>2.1.2</version>
</dependency>

プロジェクトがGradleベースの場合、同じアーティファクトをbuild.gradleファイルに追加できます。

compile 'org.pcollections:pcollections:2.1.2'

最新バージョンはMavenCentralにあります。

3. マップ構造( HashPMap

HashPMap は、永続的なマップデータ構造です。 これは、null以外のKey-Valueデータを格納するために使用されるjava.util.HashMapのアナログです。

インスタンス化できます HashPMap で便利な静的メソッドを使用する HashTreePMap。 これらの静的メソッドは、 HashPMap に裏打ちされたインスタンス IntTreePMap。

HashTreePMapクラスの静的empty()メソッドは、 java.utilのデフォルトコンストラクターを使用するのと同じように、要素を持たない空のHashPMapを作成します。 .HashMap

HashPMap<String, String> pmap = HashTreePMap.empty();

HashPMapを作成するために使用できる静的メソッドは他に2つあります。 singleton()メソッドは、次の1つのエントリのみでHashPMapを作成します。

HashPMap<String, String> pmap1 = HashTreePMap.singleton("key1", "value1");
assertEquals(pmap1.size(), 1);

from()メソッドは、既存の java.util.HashMap インスタンス(およびその他の java.util.Map実装)からHashPMapを作成します)::

Map map = new HashMap();
map.put("mkey1", "mval1");
map.put("mkey2", "mval2");

HashPMap<String, String> pmap2 = HashTreePMap.from(map);
assertEquals(pmap2.size(), 2);

HashPMapjava.util.AbstractMapおよびjava.util.Mapからいくつかのメソッドを継承していますが、それに固有のメソッドがあります。

minus()メソッドはマップから単一のエントリを削除し、 minusAll()メソッドは複数のエントリを削除します。 plus()メソッドと plusAll()メソッドもあり、それぞれ単一のエントリと複数のエントリを追加します。

HashPMap<String, String> pmap = HashTreePMap.empty();
HashPMap<String, String> pmap0 = pmap.plus("key1", "value1");

Map map = new HashMap();
map.put("key2", "val2");
map.put("key3", "val3");
HashPMap<String, String> pmap1 = pmap0.plusAll(map);

HashPMap<String, String> pmap2 = pmap1.minus("key1");

HashPMap<String, String> pmap3 = pmap2.minusAll(map.keySet());

assertEquals(pmap0.size(), 1);
assertEquals(pmap1.size(), 3);
assertFalse(pmap2.containsKey("key1"));
assertEquals(pmap3.size(), 0);

pmapput()を呼び出すと、UnsupportedOperationExceptionがスローされることに注意してください。PCollectionsオブジェクトは永続的で不変であるため、変更操作ごとに次の新しいインスタンスが返されます。オブジェクト( HashPMap )。

次に、他のデータ構造を見てみましょう。

4. リスト構造(TreePVectorおよびConsPStack

TreePVectorjava.util.ArrayListの永続的なアナログであり、ConsPStackjava.util.LinkedListのアナログです。 TreePVectorおよびConsPStackには、 HashPMap と同様に、新しいインスタンスを作成するための便利な静的メソッドがあります。

empty()メソッドは空の TreePVector を作成し、 singleton()メソッドは1つの要素のみでTreePVectorを作成します。 java .util.CollectionからTreePVectorのインスタンスを作成するために使用できるfrom()メソッドもあります。

ConsPStack には、同じ目標を達成する同じ名前の静的メソッドがあります。

TreePVector には、それを操作するためのメソッドがあります。 要素を削除するためのminus()メソッドと minusAll()メソッドがあります。 要素を追加するためのplus()、および plusAll()

with()は、指定されたインデックスの要素を置き換えるために使用され、 subList()はコレクションから要素の範囲を取得します。

これらのメソッドは、ConsPStackでも使用できます。

上記のメソッドを例示する次のコードスニペットについて考えてみましょう。

TreePVector pVector = TreePVector.empty();

TreePVector pV1 = pVector.plus("e1");
TreePVector pV2 = pV1.plusAll(Arrays.asList("e2", "e3", "e4"));
assertEquals(1, pV1.size());
assertEquals(4, pV2.size());

TreePVector pV3 = pV2.minus("e1");
TreePVector pV4 = pV3.minusAll(Arrays.asList("e2", "e3", "e4"));
assertEquals(pV3.size(), 3);
assertEquals(pV4.size(), 0);

TreePVector pSub = pV2.subList(0, 2);
assertTrue(pSub.contains("e1") && pSub.contains("e2"));

TreePVector pVW = (TreePVector) pV2.with(0, "e10");
assertEquals(pVW.get(0), "e10");

上記のコードスニペットでは、pSubは別のTreePVectorオブジェクトであり、pV2から独立しています。 観察できるように、 pV2subList()操作によって変更されませんでした。 むしろ、新しい TreePVector オブジェクトが作成され、インデックス0から2までのpV2の要素で埋められました。

これは不変性が意味するものであり、PCollectionsのすべての変更メソッドで発生することです。

5. 構造の設定( MapPSet

MapPSet は、 java.util.HashSet の永続的な、マップに裏打ちされたアナログです。 HashTreePSet – empty() from()および singleton()の静的メソッドによって便利にインスタンス化できます。 これらは、前の例で説明したのと同じように機能します。

MapPSet には、操作用の plus() plusAll() minus()、および minusAll()メソッドがあります。データを設定します。 さらに、 java.util.Set java.util.AbstractCollection 、およびjava.util.AbstractSetからメソッドを継承します。

MapPSet pSet = HashTreePSet.empty()     
  .plusAll(Arrays.asList("e1","e2","e3","e4"));
assertEquals(pSet.size(), 4);

MapPSet pSet1 = pSet.minus("e4");
assertFalse(pSet1.contains("e4"));

最後に、 OrderedPSet もあります。これは、 java.util.LinkedHashSetと同じように要素の挿入順序を維持します。

6. 結論

結論として、このクイックチュートリアルでは、Javaで利用できるコアコレクションに類似した永続データ構造であるPCollectionについて説明しました。 もちろん、PCollections Javadoc は、ライブラリの複雑さについてより多くの洞察を提供します。

そして、いつものように、完全なコードはGithubにあります。