[Guava官方文档翻译] 7. Guava的Immutable Collection(不可变集合)工具 (Immutable Collections Explained)...

我的技术博客经常被流氓网站恶意爬取转载。请移步原文:http://www.cnblogs.com/hamhog/p/3538666.html ,享受整齐的排版、有效的链接、正确的代码缩进、更好的阅读体验。

例子

public static final ImmutableSet<String> COLOR_NAMES =ImmutableSet.of(
    "red",
    "orange",
    "yellow",
    "green",
    "blue",
    "purple");
class Foo{
    Set<Bar> bars;
    Foo(Set<Bar> bars){
        this.bars =ImmutableSet.copyOf(bars);// defensive copy!
    }
}

为什么要用不可变集合?

不可变(Immutable)的对象有很多好处,包括:

  • 被不可靠的库使用的安全性
  • 线程安全:可以被多个线程同时使用,不会出现资源竞争(race condition) 
  • 因不可变而带来时间、空间效率提升。所有的不可变集合实现都比相应的可变集合效率高。(分析)
  • 可以用作常量,可以信任它不会变

使用不可变的对象副本是一项典型的防御式编程技术。Guava为每种 Collection 类型提供了简单、易用的不可变版本,也包括Guava自己的 Collection 类型。

JDK 提供 Collections.unmodifiableXXX 方法,但在我们看来,这些方法的问题是:

  • 笨重而冗长;每处你想要得到保护性副本时都这样用,会令人不爽
  • 不安全:仅当没有人持有对原来集合对象的引用时,返回的集合才是真正不可变的
  • 低效:数据结构上仍然带有所有可变集合需要的开销,包括同步修改检查,hash表里的额外空间,等等。

当你不准备修改一个collection,或者希望它保持为常量,把它保护性拷贝为一个不可变collection是个很好的做法。

重要: Guava实现的每个不可变集合都不支持null值。我们对Google的内部代码库进行了详尽无遗的研究,发现只有5%的情况下集合里可以有 null 元素,而95%的情况下对null直接报错会更好。如果你需要支持null值,考虑用 Collections.unmodifiableList 和其他允许null的类似集合实现。更详细的建议请参见这里

怎么用?

创建 ImmutableXXX 集合可用以下几种方法:

    • 用 copyOf 方法,例如, ImmutableSet.copyOf(set)
    • 用 of 方法,例如, ImmutableSet.of("a", "b", "c") 或 ImmutableMap.of("a", 1, "b", 2)
    • 用 Builder,例如,
publicstaticfinalImmutableSet<Color> GOOGLE_COLORS =
       ImmutableSet.<Color>builder()
           .addAll(WEBSAFE_COLORS)
           .add(newColor(0,191,255))
           .build();

除了有序集合之外的集合,会保留创建时元素的顺序。例如,

ImmutableSet.of("a","b","c","a","d","b")

遍历元素的顺序会是 "a", "b", "c", "d"。

copyOf 比你想象的聪明

要记住 ImmutableXXX.copyOf 会尽量避免拷贝数据,只要这样是安全的——具体的实现细节不一,但总体来说是“聪明的”。例如,

ImmutableSet<String> foobar =ImmutableSet.of("foo","bar","baz");
thingamajig(foobar);

void thingamajig(Collection<String> collection){
   ImmutableList<String> defensiveCopy =ImmutableList.copyOf(collection);
   ...
}

在这段代码中,聪明的 ImmutableList.copyOf(foobar) 会直接返回 foobar.asList(),是这个 ImmutableSet 的常量时间复杂度的拷贝。

作为一般性的探索,ImmutableXXX.copyOf(ImmutableCollection) 会尽量避免线性时间复杂度的拷贝,如果

  • 基础数据结构可以在常量时间复杂度内使用。例如, ImmutableSet.copyOf(ImmutableList) 无法在常量时间内完成。
  • 不会引起内存泄漏——例如,如果有一个很大的 ImmutableList<String> hugeList ,然后执行 ImmutableList.copyOf(hugeList.subList(0, 10)),会进行显式的拷贝,为了避免无意中保持着对 hugeList 中不必要的元素的引用。
  • 不会改变语义 —— 所以,ImmutableSet.copyOf(myImmutableSortedSet) 会进行显式的拷贝,因为 ImmutableSet 使用的 hashCode() 和 equals 与依赖 comparator 的 ImmutableSortedSet 语义不同。

这帮助了良好的防御式编程减小性能开销。

asList

所有的不可变集合都提供了转化为 ImmutableList 的方法 asList()。因此——例如——即使你把数据存为 ImmutableSortedSet 格式,你也可以用 sortedSet.asList().get(k) 得到第k个最小元素。

返回的 ImmutableList 经常是——并不是每次,但是经常——一个常量时间得到的副本,而不是显式的靠别。也就是说,它一般比普通的 List 要聪明——例如,它会知道调用底层结构的更有效率的 contains 方法。

细节

Where?

 

InterfaceJDK or Guava?Immutable Version
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

中文翻译自Guava官方文档:GuavaExplained - ImmutableCollectionsExplained 译者:戴仓薯

转载于:https://www.cnblogs.com/hamhog/p/3538666.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值