谷歌Guava与Scala集合框架比较

31

有很多常见的概念:

  • 不可变集合(immutable collection)
  • 集合视图(collection view)
  • 严格/非严格集合(strict/non-strict collection)
  • 集合构造器(collection builders)

Guava和Scala Collection API中都有相同的模式。那么它们之间有什么区别?这两个库的模式是否一致?扩展性是否足够好?

因此,我想听听同时使用它们的人对这些框架的比较。


2
很棒的问题!这两个都是我非常关心的。 - Dimitris Andreou
4个回答

26

Google Guava是一个很棒的库,毫无疑问。然而,它是用Java实现的,受到了所有相关限制的影响:

  • 在标准库中没有不可变集合接口
  • 没有lambda字面量(闭包),因此在需要例如谓词的SAM类型周围存在一些沉重的样板代码
  • 在涉及泛型的情况下,类型规格的重复很多

Guava还必须存在于Java标准集合库的存在下,因此很少有第三方库会公开支持guava兼容函数字面量或使用guava特定的集合类型。这会导致每次使用第三方库时都会出现阻抗失配。例如,您通常需要将这些库返回的集合转换为适当的guava不可变集合,尤其是在多线程环境下工作时。

Scala集合具有更好地集成到语言中的设计,您将在整个scala标准库和通过Scala实现的第三方产品中广泛使用它们。Scala集合默认也是不可变的,因此您会得到更安全的代码,无需额外的防御性封装。

如果您可以使用Scala,请这样做,它除了集合框架之外还具有许多优点。如果必须使用Java,则Guava是一个很好的选择,特别是考虑到没有Scala提供的语言功能,Scala集合并不特别容易使用。

在混合项目中,从Scala内部完全可以使用Guava集合,但语言还提供了机制,允许您像使用自己的Scala集合一样使用Java集合(包括暴露相同接口的Guava集合)。


5
标准库没有不可变集合接口。Guava必须实现可变接口并在可变方法上返回异常,这可能导致运行时异常。 - Daniel Canas
4
我认为你指出了其中一个最大的区别。虽然Guava的不可变性在运行时进行检查,但Scala的不可变性在编译时进行检查。 - paradigmatic
1
这是一个旧的帖子,但应该补充说明的是,随着Java 8的新“函数”功能,许多Guava方法将被取代。Google的人员已经意识到了这一点,尽管我不知道他们将如何整合这两个功能。 - Giovanni Botta
Guava拥有Table和Multiset的概念,而这些在Scala中尚不存在,因此它具有其附加值。 - Jas
1
@Jas - 表看起来非常像一个带有元组键的映射,尽管我可以理解为什么需要它,考虑到Java缺乏元组。至于“Multiset”;Scala只有可变版本,许多人批评了这一事实。 - Kevin Wright
显示剩余2条评论

7

我现在在所有的Java项目中都使用Guava。它为Java集合提供了一种很好的函数式风格。

然而,在Java中编写闭包意味着直接定义大量匿名类,这是冗长和无聊的。

Scala集合在设计(由于特质而导致的部分实现级联)和功能方面仍然优越。只需实现一小组方法即可创建自己的集合并获得所有Scala集合的优势。


4
其他人已经回答了你的问题,但我认为你错过了一个有趣的选择,那就是Functional Java库。它忽略了Java集合API,并提供了类似于简化版Scala集合的不可变集合。

3
我曾使用过Scala、Google collections和F#。最近我一直在使用Google collections迭代器,忽略了F#序列表达式的强大功能。似乎Scala更喜欢非严格(惰性)列表而不是迭代器/序列。
在F#和Google collections(请参见Google Iterators)中,您可以转换和过滤迭代器,创建一个表示对象流的漂亮推送管道工作。虽然Scala也可以做到这一点,但这并不常见。F#有一个很酷的管道运算符用于过滤迭代器(序列)。
例如,我希望Scala的yield表达式生成类似Python(或F#序列块)的迭代器,而不是返回一个列表。
两者非常相似,Scala在速度和语法方面具有巨大的优势,但在使用它们时,我感觉(个人意见):
- Google collections侧重于Map和Iterator。 - Scala非常专注于List。
注意:Scala 2.8似乎在其集合方面进行了一些重大改变(我使用的是较旧版本的Scala)。

1
Scala的列表是严格的,而懒惰的列表则是流。在我看来,过滤器在Scala中也很常见,但它们隐藏在for表达式的守卫中。这是你所指的吗? - paradigmatic
@paradigmatic 是的,那就是我的意思。大多数编程语言区分列表、惰性列表和流/迭代器。Scala 和 Haskell 有时会模糊这条线。这在大多数情况下都是好的,只是对我来说不太熟悉。 - Adam Gent
4
for-comprehensions 会尝试返回与输入的集合类型相同的结果集合。如果用于迭代器,通常会返回经过筛选/映射后的迭代器。 - ziggystar
2
“大变革”一词简直不足以形容。Scala 2.8集合从头开始重写,它们是完全不同的生物,更加强大和灵活。 - Kevin Wright
1
@Adam:请不要删除您的帖子。对于我们这些刚开始学习Scala的人来说,这个对话是有帮助的。 - chaotic3quilibrium
显示剩余2条评论

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