簡體   English   中英

什么是在Java中使用的良好的持久性收集框架?

[英]what's a good persistent collections framework for use in java?

永久性收集是指類似於clojure的收集。

例如,我有一個包含元素(a,b,c)的列表。 對於普通列表,如果我添加d,則原始列表將具有(a,b,c,d)作為其元素。 對於持久性列表,當我調用list.add(d)時,我會得到一個新列表,並持有(a,b,c,d)。 但是,該實現嘗試盡可能在列表之間共享元素,因此與簡單地返回原始列表的副本相比,它的內存效率要高得多。 它還具有不可變的優勢(如果我持有對原始列表的引用,那么它將始終返回原始的3個元素)。

所有這些都在其他地方(例如http://en.wikipedia.org/wiki/Persistent_data_structure )得到了更好的解釋。

無論如何,我的問題是...提供此功能以在Java中使用的最佳庫是什么? 我可以以某種方式使用clojure集合嗎(其他方式可以直接使用clojure)?

只需直接在Clojure中使用即可。 雖然顯然您可能不想使用它本身的語言,但是您仍然可以直接使用持久性集合,因為它們都是Java類。

import clojure.lang.PersistentHashMap;
import clojure.lang.IPersistentMap;

IPersistentMap map = PersistentHashMap.create("key1", "value1");

assert map.get("key1").equals("value1");
IPersistentMap map2 = map.assoc("key1", "value1");

assert map2 != map;
assert map2.get("key1").equals("value1");

(免責聲明:我實際上尚未編譯該代碼:)

缺點是沒有鍵入集合,即它們沒有泛型。

收集呢?

您還可以檢查Clojure的持久性集合的實現(例如PersistentHashMap )。

我一直在尋找一個苗條的Java“友好”持久性收集框架,並將該線程中提到的TotallyLazyPCollections用於測試驅動器,因為它們聽起來對我來說最有希望。

兩者都提供合理的簡單接口來操作持久列表:

// TotallyLazy
PersistentList<String> original = PersistentList.constructors.empty(String.class);
PersistentList<String> modified = original.append("Mars").append("Raider").delete("Raider");

// PCollections
PVector<String> original = TreePVector.<String>empty();
PVector<String> modified = original.plus("Mars").plus("Raider").minus("Raider");

PersistentListPVector擴展了java.util.List ,因此這兩個庫都應很好地集成到現有環境中。

但是事實證明,在處理較大的列表時,TotallyLazy會遇到性能問題 (如@levantpied在上面的注釋中已經提到的)。 在我的MacBook Pro(2013年末)上,插入100.000個元素並返回不可變的列表花費了TotallyLazy〜2000ms,而PCollections在〜120ms內完成。

如果有人想更全面地了解我的(簡單)測試用例,可以在Bitbucket上找到。

[更新] :最近我查看了Cyclops X ,它是針對函數式編程的高性能且更完整的庫。 獨眼巨人還包含一個用於持久性收集的模塊。

https://github.com/andrewoma/dexx是Scala的持久性集合到Java的移植。 這包括:

  • Set,SortedSet,Map,SortedMap和Vector
  • 適配器以java.util等效項查看持久性集合
  • 輕松施工的助手

功能性Java實現了一個持久列表,惰性列表,集合,映射和樹。 可能還有其他內容,但是我只是瀏覽網站首頁上的信息。

我也想知道Java最好的持久性數據結構庫是什么。 我的注意力集中在Functional Java上,因為在《 Java開發人員的函數式編程 》一書中提到了它。

您可以使用pcollections (永久集合)庫:

http://code.google.com/p/pcollections/

投票最多的答案建議直接使用clojure集合,我認為這是一個很好的主意。 不幸的是,clojure是一種動態類型化的語言,而Java並不是這樣的事實,這使得clojure庫在Java中使用起來非常不舒服。

因此,由於缺少用於Clojure集合類型的輕巧,易於使用的包裝器,我編寫了自己的Java包裝器庫,使用了用於Clojure集合類型的泛型,並着眼於易用性和清晰度到接口。

https://github.com/cornim/ClojureCollections

也許這對某人有用。

PS:目前只實現了PersistentVector,PersistentMap和PersistentList。

Paguro提供了Java 8+中使用的實際Clojure集合的類型安全版本 它包括:列表(向量),HashMap,TreeMap,HashSet和TreeSet。 它們的行為完全符合您在問題中指定的方式,並且已盡力地適合現有的java.util集合接口,以實現最大的類型安全Java兼容性。 它們也比PCollections快一點

用Paguro編碼示例如下:

// List with the elements (a,b,c)
ImList<T> list = vec(a,b,c);

// With a persistent list, when I call list.add(d),
// I get back a new list, holding (a,b,c,d)
ImList<T> newList = list.append(d);

list.size(); // still returns 3

newList.size(); // returns 4

你說,

該實現嘗試盡可能在列表之間共享元素,因此與簡單地返回原始列表的副本相比,它具有更高的內存效率和速度。 它還具有不可變的優勢(如果我持有對原始列表的引用,那么它將始終返回原始的3個元素)。

是的,這就是它的行為方式。 丹尼爾·斯皮沃克(Daniel Spiewak)解釋了這些收藏的速度和效率要比我更好。

可能想查看clj-ds 我沒有用過,但看起來很有希望。 基於項目自述文件,它從Clojure 1.2.0中提取了數據結構。

與Cornelius Mund一樣, Pure4J將Clojure集合移植到Java中並添加了對Generics的支持。

但是,Pure4J旨在通過編譯時代碼檢查將純編程語義引入JVM,因此進一步將不可變性約束引入您的類,以便在存在該集合的情況下不能使該集合的元素發生突變。

這可能不是您想要實現的目標:如果只是在JVM上使用Clojure集合后,我會采用Cornelius的方法,否則,如果您有興趣在Java中追求純編程方法,那么您可以Pure4J試試。

披露:我是這個的開發商

totallylazy是一個非常好的FP庫,具有以下實現:

  • PersistentList<T> :具體的實現是LinkedList<T>TreeList<T> (用於隨機訪問)
  • PersistentMap<K, V> :具體的實現是HashTreeMap<K, V>ListMap<K, V>
  • PersistentSortedMap<K, V>
  • PersistentSet<T> :具體的實現是TreeSet<T>

用法示例:

import static com.googlecode.totallylazy.collections.PersistentList.constructors.*;
import com.googlecode.totallylazy.collections.PersistentList;
import com.googlecode.totallylazy.numbers.Numbers;

...

PersistentList<Integer> list = list(1, 2, 3);

// Create a new list with 0 prepended
list = list.cons(0);

// Prints 0::1::2::3
System.out.println(list);

// Do some actions on this list (e.g. remove all even numbers)
list = list.filter(Numbers.odd);
// Prints 1::3
System.out.println(list);

完全懶惰不斷被維護。 主要缺點是完全缺少Javadoc。

我很驚訝沒有人提到vavr。 我已經使用了很長時間了。

http://www.vavr.io

來自他們網站的描述:

Vavr核心是Java的功能庫。 它有助於減少代碼量並提高魯棒性。 進行函數式編程的第一步是開始思考不變的值。 Vavr提供不可變的集合以及必要的功能和控制結構,以對這些值進行操作。 結果是美麗的,並且可以正常工作。

https://github.com/arnohaase/a-foundation是Scala庫的另一個端口。

也可以從Maven Central獲得:com.ajjpj.a-foundation:a-foundation

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM