Google_Guava官方教程(中文版)2.1 不可變集合
reprint
Fri Oct 01 20:48:00 CST 2010

不可变集合

范例

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!
    }
}

为什么要使用不可变集合

不可变对象有很多优点,包括:

创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava为所有JDK标准集合类型和 Guava新集合类型都提供了简单易用的不可变版本。

JDK也提供了Collections.unmodifiableXXX方法把集合包装为不可变形式,但我们认为不够 好:

如果你没有修改某个集合的需求,或者希望某个集合保持不变时,把它防御性地拷贝到不可变集合是个很好的实践。 重要提示:所有Guava不可变集合的实现都不接受null值。我们对Google内部的代码库做过详细研究,发现只有5%的情况需要在集合 中允许null元素,剩下的95%场景都是遇到null值就快速失败。如果你需要在不可变集合中使用null,请使用JDK中的 Collections.unmodifiableXXX方法。更多细节建议请参考“使用和避免null”。

怎么使用不可变集合

不可变集合可以用如下多种方式创建:

此外,对有序不可变集合来说,排序是在构造集合的时候完成的,如:

ImmutableSortedSet.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的常量时间复杂度的List视图。

作为一种探索,ImmutableXXX.copyOf(ImmutableCollection)会试图对如下情况避免线性时 间拷贝:

asList视图

所有不可变集合都有一个asList()方法提供ImmutableList视图,来帮助你用列表形式方便 地读取集合元素。例如,你可以使用sortedSet.asList().get(k)从ImmutableSortedSet中 读取第k个最小元素。asList()返回的ImmutableList通常是——并不总是——开销稳定的视图实 现,而不是简单地把元素拷贝进List。也就是 说,asList返回的列表视图通常比一般的列 表平均性能更好,比如,在底层集合支持的情况下,它总是使用高效的contains方法。

细节:关联可变集合和不可变集合

Collection JDK ImmutableCollection
List JDK ImmutableList
Set JDK ImmutableSet
SortedSet/NavigableSet JDK ImmutableSortedSet
Map JDK ImmutableMap
SortedMap JDK ImmutableSortedMap
Multiset Guava ImmutableMultiset
SortedMultiset Guava ImmutableSortedMultiset
Multimap Guava ImmutableMultimap
ListMultimap Guava ImmutableListMultimap
SetMultimap Guava ImmutableSetMultimap
BiMap Guava ImmutableBiMap
ClassToInstanceMap Guava ImmutableClassToInstanceMap
Table Guava ImmutableTable
其它文章