什么是在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中提供此function的最佳库是什么? 我可以以某种方式使用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"); 

(免责声明:我实际上没有编译那段代码:)

缺点是集合没有输入,即它们没有generics。

pcollections怎么样?

您还可以查看Clojure的持久集合实现(例如PersistentHashMap )。

我一直在寻找一个苗条的,Java“友好”的持久性收集框架,并将TotallyLazy和PCollections在这个post中提到了一个testdrive,因为它们对我来说听起来最有希望。

两者都提供合理的简单接口来操作持久列表:

 // TotallyLazy PersistentList original = PersistentList.constructors.empty(String.class); PersistentList modified = original.append("Mars").append("Raider").delete("Raider"); // PCollections PVector original = TreePVector.empty(); PVector modified = original.plus("Mars").plus("Raider").minus("Raider"); 

PersistentListPVector扩展了java.util.List ,因此这两个库应该很好地集成到现有环境中。

然而,事实certificate,TotallyLazy在处理更大的列表时会遇到性能问题 (正如@levantpied上面的评论中已经提到的那样)。 在我的MacBook Pro(2013年末)上插入100.000个元素并返回不可变列表需要TotallyLazy~2000ms,而PCollections在~120ms内完成。

我的(简单)测试用例可以在Bitbucket上获得 ,如果有人想要更彻底的看。

https://github.com/andrewoma/dexx是Scala对Java的持久集合的一个端口。 这包括:

  • Set,SortedSet,Map,SortedMap和Vector
  • 用于将持久性集合视为java.util等效项的适配器
  • 辅助工具,易于施工

可能想看看clj-ds 。 我没有用它,但看起来很有希望。 基于项目自述文件,它从Clojure 1.2.0中提取出数据结构。

Functional Java实现了持久List,惰性List,Set,Map和Tree。 可能还有其他人,但我只是通过网站首页上的信息。

我也很想知道Java最好的持久数据结构库是什么。 我的注意力集中在functionJava上,因为在Java开发人员的function编程一书中提到了它。

您可以使用pcollections (Persistent Collections)库:

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

Paguro提供了用于Java 8+ 的实际Clojure集合的类型安全版本 。 它包括:List(Vector),HashMap,TreeMap,HashSet和TreeSet。 它们的行为与您在问题中指定的方式完全相同,并且非常适合现有的java.util集合接口,以实现最大的类型安全Java兼容性。 它们也比PCollections快一点 。

在Paguro中编写您的示例看起来像这样:

 // List with the elements (a,b,c) ImList 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 newList = list.append(d); list.size(); // still returns 3 newList.size(); // returns 4 

你说,

该实现尝试尽可能地在列表之间共享元素,因此与仅返回原始列表的副本相比,它具有更高的内存效率和快速性。 它还具有不可变的优点(如果我持有对原始列表的引用,那么它将始终返回原始的3个元素)。

是的,这正是它的表现。 Daniel Spiewak比我更好地解释了这些系列的速度和效率 。

与Cornelius Mund一样, Pure4J将Clojure集合移植到Java中并添加了Generics支持。

但是,Pure4J旨在通过编译时代码检查将纯编程语义引入JVM,因此它进一步向类引入不可变性约束,以便在集合存在时不能突变集合的元素。

这可能是你想要实现的,也可能不是你想要实现的:如果你刚刚在JVM上使用Clojure集合,我会采用Cornelius的方法,否则,如果你有兴趣在Java中寻求纯编程方法那么你可以给Pure4J一试。

披露:我是这方面的开发者

最高投票的答案建议直接使用clojure集合,我认为这是一个非常好的主意。 不幸的是,clojure是一种动态类型语言而Java不会使clojure库在Java中使用时非常不舒服。

由于这个以及缺乏轻量级,易于使用的clojure集合类型的包装器,我已经编写了我自己的Java包装器库,使用generics用于clojure集合类型,重点是易用性和清晰度到接口。

https://github.com/cornim/ClojureCollections

也许这会对某人有用。

PS:目前只实现了PersistentVector,PersistentMap和PersistentList。

totallylazy是一个非常好的FP库,具有以下实现:

  • PersistentList :具体实现是LinkedListTreeList (用于随机访问)
  • PersistentMap :具体实现是HashTreeMapListMap
  • PersistentSortedMap
  • PersistentSet :具体实现是TreeSet

用法示例:

 import static com.googlecode.totallylazy.collections.PersistentList.constructors.*; import com.googlecode.totallylazy.collections.PersistentList; import com.googlecode.totallylazy.numbers.Numbers; ... PersistentList 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 (eg remove all even numbers) list = list.filter(Numbers.odd); // Prints 1::3 System.out.println(list); 

完全保持不变。 主要缺点是完全没有Javadoc。

我很惊讶没人提到vavr。 我现在用它很久了。

http://www.vavr.io

他们网站的描述:

Vavr核心是Java的function库。 它有助于减少代码量并增强稳健性。 函数式编程的第一步是开始考虑不可变的值。 Vavr提供不可变集合以及操作这些值的必要函数和控制结构。 结果很美,只是工作。

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

它也可以从Maven Central获得:com.ajjpj.a-foundation:a-foundation