bm2*_*212 29 java collections functional-programming clojure
通过持久性集合,我的意思是像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)?
Gar*_*vis 16
只需直接使用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");
Run Code Online (Sandbox Code Playgroud)
(免责声明:我实际上没有编译该代码:)
缺点是集合没有输入,即它们没有泛型.
我一直在寻找一个苗条的,Java"友好"的持久性收集框架,并将TotallyLazy和PCollections在这个帖子中提到了一个testdrive,因为它们对我来说听起来最有希望.
两者都提供合理的简单接口来操作持久列表:
// 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");
Run Code Online (Sandbox Code Playgroud)
无论PersistentList和PVector延长java.util.List,所以这两个库应该很好地集成到现有环境中.
然而,事实证明,TotallyLazy 在处理更大的列表时会遇到性能问题(正如@levantpied上面的评论中已经提到的那样).在我的MacBook Pro(2013年末)上插入100.000个元素并返回不可变列表,取TotallyLazy~2000ms,而PCollections在~120ms内完成.
我的(简单)测试用例可以在Bitbucket上获得,如果有人想要更彻底的看.
小智 5
https://github.com/andrewoma/dexx是 Scala 的持久集合到 Java 的端口。这包括:
Paguro 提供了实际 Clojure 集合的类型安全版本,以便在 Java 8+ 中使用。包括:List(Vector)、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
Run Code Online (Sandbox Code Playgroud)
你说,
该实现尝试尽可能在列表之间共享元素,因此它比简单地返回原始列表的副本更加内存高效且快速。它还具有不可变的优点(如果我持有对原始列表的引用,那么它将始终返回原始的 3 个元素)。
是的,这正是它的行为方式。 Daniel Spiewak比我更好地解释了这些集合的速度和效率。
| 归档时间: |
|
| 查看次数: |
7539 次 |
| 最近记录: |