简体   繁体   English

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

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

By persistent collections I mean collections like those in clojure. 永久性收集是指类似于clojure的收集。

For example, I have a list with the elements (a,b,c). 例如,我有一个包含元素(a,b,c)的列表。 With a normal list, if I add d, my original list will have (a,b,c,d) as its elements. 对于普通列表,如果我添加d,则原始列表将具有(a,b,c,d)作为其元素。 With a persistent list, when I call list.add(d), I get back a new list, holding (a,b,c,d). 对于持久性列表,当我调用list.add(d)时,我会得到一个新列表,并持有(a,b,c,d)。 However, the implementation attempts to share elements between the list wherever possible, so it's much more memory efficient than simply returning a copy of the original list. 但是,该实现尝试尽可能在列表之间共享元素,因此与简单地返回原始列表的副本相比,它的内存效率要高得多。 It also has the advantage of being immutable (if I hold a reference to the original list, then it will always return the original 3 elements). 它还具有不可变的优势(如果我持有对原始列表的引用,那么它将始终返回原始的3个元素)。

This is all explained much better elsewhere (eg http://en.wikipedia.org/wiki/Persistent_data_structure ). 所有这些都在其他地方(例如http://en.wikipedia.org/wiki/Persistent_data_structure )得到了更好的解释。

Anyway, my question is... what's the best library for providing this functionality for use in java? 无论如何,我的问题是...提供此功能以在Java中使用的最佳库是什么? Can I use the clojure collections somehow (other that by directly using clojure)? 我可以以某种方式使用clojure集合吗(其他方式可以直接使用clojure)?

Just use the ones in Clojure directly. 只需直接在Clojure中使用即可。 While obviously you might not want to use the language it's self, you can still use the persistent collections directly as they are all just Java classes. 虽然显然您可能不想使用它本身的语言,但是您仍然可以直接使用持久性集合,因为它们都是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");

(disclaimer: I haven't actually compiled that code :) (免责声明:我实际上尚未编译该代码:)

the down side is that the collections aren't typed, ie there are no generics with them. 缺点是没有键入集合,即它们没有泛型。

What about pcollections ? 收集呢?

You can also check out Clojure 's implementation of persistent collections ( PersistentHashMap , for instance). 您还可以检查Clojure的持久性集合的实现(例如PersistentHashMap )。

I was looking for a slim, Java "friendly" persistent collection framework and took TotallyLazy and PCollections mentioned in this thread for a testdrive, because they sounded most promising to me. 我一直在寻找一个苗条的Java“友好”持久性收集框架,并将该线程中提到的TotallyLazyPCollections用于测试驱动器,因为它们听起来对我来说最有希望。

Both provide reasonable simple interfaces to manipulate persistent lists: 两者都提供合理的简单接口来操作持久列表:

// 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");

Both PersistentList and PVector extend java.util.List , so both libraries should integrate well into an existing environment. PersistentListPVector扩展了java.util.List ,因此这两个库都应很好地集成到现有环境中。

It turns out, however, that TotallyLazy runs into performance problems when dealing with larger lists (as already mentioned in a comment above by @levantpied). 但是事实证明,在处理较大的列表时,TotallyLazy会遇到性能问题 (如@levantpied在上面的注释中已经提到的)。 On my MacBook Pro (Late 2013) inserting 100.000 elements and returning the immutable list took TotallyLazy ~2000ms, whereas PCollections finished within ~120ms. 在我的MacBook Pro(2013年末)上,插入100.000个元素并返回不可变的列表花费了TotallyLazy〜2000ms,而PCollections在〜120ms内完成。

My (simple) test cases are available on Bitbucket , if someone wants to take a more thorough look. 如果有人想更全面地了解我的(简单)测试用例,可以在Bitbucket上找到。

[UPDATE] : I recently had a look at Cyclops X , which is a high performing and more complete lib targeted for functional programming. [更新] :最近我查看了Cyclops X ,它是针对函数式编程的高性能且更完整的库。 Cyclops also contains a module for persistent collections. 独眼巨人还包含一个用于持久性收集的模块。

https://github.com/andrewoma/dexx is a port of Scala's persistent collections to Java. https://github.com/andrewoma/dexx是Scala的持久性集合到Java的移植。 It includes: 这包括:

  • Set, SortedSet, Map, SortedMap and Vector Set,SortedSet,Map,SortedMap和Vector
  • Adapters to view the persistent collections as java.util equivalents 适配器以java.util等效项查看持久性集合
  • Helpers for easy construction 轻松施工的助手

Functional Java implements a persistent List, lazy List, Set, Map, and Tree. 功能性Java实现了一个持久列表,惰性列表,集合,映射和树。 There may be others, but I'm just going by the information on the front page of the site. 可能还有其他内容,但是我只是浏览网站首页上的信息。

I am also interested to know what the best persistent data structure library for Java is. 我也想知道Java最好的持久性数据结构库是什么。 My attention was directed to Functional Java because it is mentioned in the book, Functional Programming for Java Developers . 我的注意力集中在Functional Java上,因为在《 Java开发人员的函数式编程 》一书中提到了它。

There's pcollections (Persistent Collections) library you can use: 您可以使用pcollections (永久集合)库:

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

The top voted answer suggest to directly use the clojure collections which I think is a very good idea. 投票最多的答案建议直接使用clojure集合,我认为这是一个很好的主意。 Unfortunately the fact that clojure is a dynamically typed language and Java is not makes the clojure libraries very uncomfortable to use in Java. 不幸的是,clojure是一种动态类型化的语言,而Java并不是这样的事实,这使得clojure库在Java中使用起来非常不舒服。

Because of this and the lack of light-weight, easy-to-use wrappers for the clojure collections types I have written my own library of Java wrappers using generics for the clojure collection types with a focus on ease of use and clarity when it comes to interfaces. 因此,由于缺少用于Clojure集合类型的轻巧,易于使用的包装器,我编写了自己的Java包装器库,使用了用于Clojure集合类型的泛型,并着眼于易用性和清晰度到接口。

https://github.com/cornim/ClojureCollections https://github.com/cornim/ClojureCollections

Maybe this will be of use to somebody. 也许这对某人有用。

PS: At the moment only PersistentVector, PersistentMap and PersistentList have been implemented. PS:目前只实现了PersistentVector,PersistentMap和PersistentList。

Paguro provides type-safe versions of the actual Clojure collections for use in Java 8+. Paguro提供了Java 8+中使用的实际Clojure集合的类型安全版本 It includes: List (Vector), HashMap, TreeMap, HashSet, and TreeSet. 它包括:列表(向量),HashMap,TreeMap,HashSet和TreeSet。 They behave exactly the way you specify in your question and have been painstakingly fit into the existing java.util collections interfaces for maximum type-safe Java compatibility. 它们的行为完全符合您在问题中指定的方式,并且已尽力地适合现有的java.util集合接口,以实现最大的类型安全Java兼容性。 They are also a little faster than PCollections . 它们也比PCollections快一点

Coding your example in Paguro looks like this: 用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

You said, 你说,

The implementation attempts to share elements between the list wherever possible, so it's much more memory efficient and fast than simply returning a copy of the original list. 该实现尝试尽可能在列表之间共享元素,因此与简单地返回原始列表的副本相比,它具有更高的内存效率和速度。 It also has the advantage of being immutable (if I hold a reference to the original list, then it will always return the original 3 elements). 它还具有不可变的优势(如果我持有对原始列表的引用,那么它将始终返回原始的3个元素)。

Yes, that's exactly how it behaves. 是的,这就是它的行为方式。 Daniel Spiewak explains the speed and efficiency of these collections much better than I could. 丹尼尔·斯皮沃克(Daniel Spiewak)解释了这些收藏的速度和效率要比我更好。

May want to check out clj-ds . 可能想查看clj-ds I haven't used it, but it seems promising. 我没有用过,但看起来很有希望。 Based off of the projects readme it extracted the data structures out of Clojure 1.2.0. 基于项目自述文件,它从Clojure 1.2.0中提取了数据结构。

In the same vein as Cornelius Mund, Pure4J ports the Clojure collections into Java and adds Generics support. 与Cornelius Mund一样, Pure4J将Clojure集合移植到Java中并添加了对Generics的支持。

However, Pure4J is aimed at introducing pure programming semantics to the JVM through compile time code checking, so it goes further to introduce immutability constraints to your classes, so that the elements of the collection cannot be mutated while the collection exists. 但是,Pure4J旨在通过编译时代码检查将纯编程语义引入JVM,因此进一步将不可变性约束引入您的类,以便在存在该集合的情况下不能使该集合的元素发生突变。

This may or may not be what you want to achieve: if you are just after using the Clojure collections on the JVM I would go with Cornelius' approach, otherwise, if you are interested in pursuing a pure programming approach within Java then you could give Pure4J a try. 这可能不是您想要实现的目标:如果只是在JVM上使用Clojure集合后,我会采用Cornelius的方法,否则,如果您有兴趣在Java中追求纯编程方法,那么您可以Pure4J试试。

Disclosure: I am the developer of this 披露:我是这个的开发商

totallylazy is a very good FP library which has implementations of: totallylazy是一个非常好的FP库,具有以下实现:

  • PersistentList<T> : the concrete implementations are LinkedList<T> and TreeList<T> (for random access) PersistentList<T> :具体的实现是LinkedList<T>TreeList<T> (用于随机访问)
  • PersistentMap<K, V> : the concrete implementations are HashTreeMap<K, V> and ListMap<K, V> PersistentMap<K, V> :具体的实现是HashTreeMap<K, V>ListMap<K, V>
  • PersistentSortedMap<K, V>
  • PersistentSet<T> : the concrete implementation is TreeSet<T> PersistentSet<T> :具体的实现是TreeSet<T>

Example of usage: 用法示例:

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);

totallylazy is constantly being maintained. 完全懒惰不断被维护。 The main disadvantage is the total absence of Javadoc. 主要缺点是完全缺少Javadoc。

I'm surprised nobody mentioned vavr. 我很惊讶没有人提到vavr。 I use it for a long time now. 我已经使用了很长时间了。

http://www.vavr.io http://www.vavr.io

Description from their site: 来自他们网站的描述:

Vavr core is a functional library for Java. Vavr核心是Java的功能库。 It helps to reduce the amount of code and to increase the robustness. 它有助于减少代码量并提高鲁棒性。 A first step towards functional programming is to start thinking in immutable values. 进行函数式编程的第一步是开始思考不变的值。 Vavr provides immutable collections and the necessary functions and control structures to operate on these values. Vavr提供不可变的集合以及必要的功能和控制结构,以对这些值进行操作。 The results are beautiful and just work. 结果是美丽的,并且可以正常工作。

https://github.com/arnohaase/a-foundation is another port of Scala's libraries. https://github.com/arnohaase/a-foundation是Scala库的另一个端口。

It is also available from Maven Central: com.ajjpj.a-foundation:a-foundation 也可以从Maven Central获得:com.ajjpj.a-foundation:a-foundation

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM