![](/img/trans.png)
[英]What is/are the Python equivalent(s) to the Java Collections Framework?
[英]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“友好”持久性收集框架,並將該線程中提到的TotallyLazy和PCollections用於測試驅動器,因為它們聽起來對我來說最有希望。
兩者都提供合理的簡單接口來操作持久列表:
// 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");
PersistentList
和PVector
擴展了java.util.List
,因此這兩個庫都應很好地集成到現有環境中。
但是事實證明,在處理較大的列表時,TotallyLazy會遇到性能問題 (如@levantpied在上面的注釋中已經提到的)。 在我的MacBook Pro(2013年末)上,插入100.000個元素並返回不可變的列表花費了TotallyLazy〜2000ms,而PCollections在〜120ms內完成。
如果有人想更全面地了解我的(簡單)測試用例,可以在Bitbucket上找到。
[更新] :最近我查看了Cyclops X ,它是針對函數式編程的高性能且更完整的庫。 獨眼巨人還包含一個用於持久性收集的模塊。
https://github.com/andrewoma/dexx是Scala的持久性集合到Java的移植。 這包括:
功能性Java實現了一個持久列表,惰性列表,集合,映射和樹。 可能還有其他內容,但是我只是瀏覽網站首頁上的信息。
我也想知道Java最好的持久性數據結構庫是什么。 我的注意力集中在Functional Java上,因為在《 Java開發人員的函數式編程 》一書中提到了它。
您可以使用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中提取了數據結構。
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。 我已經使用了很長時間了。
來自他們網站的描述:
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.