Java中的函数式数据结构

10

Java标准库中是否有任何函数式数据结构,例如不可变的Set、List等,并支持函数式更新?


你想要列表中所有对象的深拷贝,还是只需要一个函数,它会给你一个新的指针列表,所有指针都指向源对象? - Nathan Feger
我想要一个持久化数据结构来实现Set,而不是以愚蠢的方式实现。例如,一个不可变的列表可以通过将所有元素复制到新列表并添加元素来实现添加 - O(n)。或者它可以是一个链表,将元素添加到头部并返回头部 - O(1)。 - Claudiu
在Java中,没有通用的“深拷贝”任何东西的方法。 - Kevin Bourrillion
10个回答

15

2
请看pcollections项目:

PCollections是Java Collections Framework的持久且不可变的替代品。它包含了高效、线程安全、通用、不可变和持久的栈、映射、向量、集合和背包,与它们在Java Collections中的对应物兼容。

持久和不可变的数据类型越来越受到赞赏,因为它们是可设计、并发友好,有时比可变的数据类型更节省时间和空间。


1

你不需要使用Scala,只需将你的集合传递到:

java.util.Collections.unmodifiableCollection(/* Collection<? extends T> c */);
java.util.Collections.unmodifiableSet(Set s);
java.util.Collections.unmodifiableMap(Map m);
java.util.Collections.unmodifiableList(List l);

我刚从另一个SO问题中看到了这个:
Google的ImmutableSet

http://google-collections.googlecode.com/svn/trunk/javadoc/com/google/common/collect/ImmutableSet.html

来自文档:

与 Collections.unmodifiableSet(java.util.Set) 不同的是,该集合视图是可以更改的,而此类的实例包含其自己的私有数据,并且永远不会更改。 这个类非常适合公共静态最终设置(“常量集”),并且还可以让您轻松地创建一个由调用者提供给您的类的“防御性副本”的集合。

编辑以纳入评论。


+1:你很快 =)顺便提一下,在java.util.Collections API中还有unmodifiableList()unmodifiableMap()等更多方法可用:http://java.sun.com/javase/6/docs/api/java/util/Collections.html - BalusC
我想向一个Set中添加一些内容,保持原来的Set不变,并返回一个新的Set。我认为unmodifiableSet不能做到这一点? - Claudiu
@Claudiu 是的,unmodifiableSet 肯定不会这样做。 - Nathan Feger
3
"Immutable"和"unmodifiable"不是同一回事。试图改变一个不可修改的集合将导致RuntimeException异常,而对于不可变的集合,这样的改变根本不可能,因此在运行时代码保证不会崩溃。(如果您不理解我的意思,请查看fj.data.List的源代码。) - missingfaktor

1

听起来你正在寻找Scala。它可以编译成.class文件,这就足够好了,对吧?


嗯,也许吧。我们在课程中得到了一些支持代码,它的功能是函数式的(即将某些内容添加到结构中会返回一个带有更新的新版本),但它是通过始终复制旧结构并向其添加新内容来编写的。这让我很难过。我想知道是否有一种更好的简单方法,但我猜Java可能会让它变得更加困难。 - Claudiu

1

嗯,对于“更改”不可变集合有两种可能的方法:

  • 复制包含“更改”的集合

  • 创建一个新的、不同的对象,由原始对象的引用和更改描述的引用组成。

Clojure采用后一种方法,因此可以相对快速地创建许多原始集合的兄弟集合,每个集合都有小的更正,具有合理的内存要求。但大多数Java代码倾向于选择第一种选项。

值得一提的是,Google创建了一些支持函数式编程的集合:http://code.google.com/p/google-collections/,但我还没有深入研究过它们。


1

看到有人提到了Google Collections确实很不错,但是很抱歉,我们并没有这个库。我也不知道是否有任何Java库可以替代它。在Google内部,我们实现了一些函数List结构,然而令人意外的是,几乎没有人使用它们。因此,它们不太可能会在短期内成为开源项目。


1
我知道这是一个老问题,但是搜索一番后告诉我现在我们有了另一种Functional Java的替代品。

JavasLang看起来是一个有趣的库,用于Java中的声明式编程和函数式数据结构。

我还没有比较它与Functional Java在易用性和性能方面的差异,但我很想得到任何指针。


0

在函数式编程中,字符串和数字是不可变的,但大多数集合都不是(不可变集合在添加、删除等操作时会抛出异常)。CopyOnWriteArrayListCopyOnWriteArraySet 在这方面最接近。


0
如果你对函数式风格的集合操作感兴趣,可以看看 lambdaj

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接