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();
我們可以使用其他兩種靜態方法來創建HashPMap 。 singleton()方法僅使用一個條目創建一個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.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);
重要的是要注意,在pmap上調用put()將引發UnsupportedOperationException。由於PCollections對像是持久性且不可變的,因此每個修改操作都會返回對象的新實例( HashPMap )。
讓我們繼續看其他數據結構。
4.列表結構( TreePVector和ConsPStack )
TreePVector是java.util.ArrayList的持久類似物,而ConsPStack是java.util.LinkedList的類似物。 TreePVector和ConsPStack具有用於創建新實例的便捷靜態方法,就像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 )
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一樣。
六,結論
最後,在本快速教程中,我們探討了PCollections –與我們在Java中可用的核心集合類似的持久數據結構。當然,PCollections Javadoc提供了對庫複雜性的更多了解。
和往常一樣,完整的代碼可以在Github上找到。