PCollections簡介

1.概述

在本文中,我們將研究PCollections ,這是一個提供持久性,不可變集合Java庫。

持久數據結構(集合)不能在更新操作期間直接修改,而是返回一個具有更新操作結果的新對象。它們不僅是不可變的,而且是持久的–這意味著在執行修改後,集合的先前版本保持不變。

PCollections類似於Java Collections框架並與之兼容。

2.依存關係

讓我們在pom.xml中添加以下依賴項,以便我們在項目中使用PCollections:

<dependency>

 <groupId>org.pcollections</groupId>

 <artifactId>pcollections</artifactId>

 <version>2.1.2</version>

 </dependency>

如果我們的項目基於Gradle,則可以將相同的工件添加到build.gradle文件中:

compile 'org.pcollections:pcollections:2.1.2'

最新版本可以在Maven Central上找到。

3.地圖結構( HashPMap

HashPMap是一種持久性地圖數據結構。它是java.util.HashMap的類似物,用於存儲非null的鍵值數據。

我們可以使用HashTreePMap中的便捷靜態方法來實例化HashPMap 這些靜態方法返回一個由IntTreePMap支持的HashPMap實例

HashTreePMap類的static empty()方法創建一個沒有元素的空HashPMap ,就像使用java.util.HashMap的默認構造函數一樣:

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

我們可以使用其他兩種靜態方法來創建HashPMapsingleton()方法僅使用一個條目創建一個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);

儘管HashPMap繼承了java.util.AbstractMapjava.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);

重要的是要注意,在pmap上調用put()將引發UnsupportedOperationException。由於PCollections對像是持久性且不可變的,因此每個修改操作都會返回對象的新實例( HashPMap )。

讓我們繼續看其他數據結構。

4.列表結構( TreePVector和ConsPStack

TreePVectorjava.util.ArrayList的持久類似物,而ConsPStackjava.util.LinkedList的類似物。 TreePVectorConsPStack具有用於創建新實例的便捷靜態方法,就像HashPMap一樣。

empty()方法創建一個空的TreePVector ,而singleton()方法創建一個僅包含一個元素的TreePVector 。還有from()方法可用於從任何java.util.Collection創建TreePVector的實例。

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 。可以看出, pV2未被subList()操作更改;而是創建了一個新的TreePVector對象,並用從索引0到2的pV2元素填充。

這就是不變性的含義,它是所有PCollections修改方法所發生的。

5.設置結構( MapPSet

MapPSetjava.util.HashSet的持久性,受地圖支持的類似物。可以通過HashTreePSet的靜態方法方便地實例化 empty()from()singleton() 。它們的功能與前面示例中說明的相同。

MapPSet具有plus()plusAll()minus()minusAll()方法來處理集合數據。此外,它從java.util.Setjava.util.AbstractCollectionjava.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一樣。

六,結論

最後,在本快速教程中,我們探討了PCollections –與我們在Java中可用的核心集合類似的持久數據結構。當然,PCollections Javadoc提供了對庫複雜性的更多了解。

和往常一樣,完整的代碼可以在Github上找到。