博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[Google Guava] 2.1-不可变集合
阅读量:5804 次
发布时间:2019-06-18

本文共 2752 字,大约阅读时间需要 9 分钟。

 译者:沈义扬

范例

public static final ImmutableSet
COLOR_NAMES = ImmutableSet.of( "red", "orange", "yellow", "green", "blue", "purple");class Foo { Set
bars; Foo(Set
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”

怎么使用不可变集合

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

  • copyOf方法,如ImmutableSet.copyOf(set);
  • of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
  • Builder工具,如
public static final ImmutableSet
GOOGLE_COLORS = ImmutableSet.
builder() .addAll(WEBSAFE_COLORS) .add(new Color(0, 191, 255)) .build();

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

ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");

会在构造时就把元素排序为a, b, c, d。

比想象中更智能的copyOf

请注意,ImmutableXXX.copyOf方法会尝试在安全的时候避免做拷贝——实际的实现细节不详,但通常来说是很智能的,比如:

ImmutableSet
foobar = ImmutableSet.of("foo", "bar", "baz");thingamajig(foobar);void thingamajig(Collection
collection) { ImmutableList
defensiveCopy = ImmutableList.copyOf(collection); ...}

在这段代码中,ImmutableList.copyOf(foobar)会智能地直接返回foobar.asList(),它是一个ImmutableSet的常量时间复杂度的List视图。

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

  • 在常量时间内使用底层数据结构是可能的——例如,ImmutableSet.copyOf(ImmutableList)就不能在常量时间内完成。
  • 不会造成内存泄露——例如,你有个很大的不可变集合ImmutableList<String>
    hugeList, ImmutableList.copyOf(hugeList.subList(0, 10))就会显式地拷贝,以免不必要地持有hugeList的引用。
  • 不改变语义——所以ImmutableSet.copyOf(myImmutableSortedSet)会显式地拷贝,因为和基于比较器的ImmutableSortedSet相比,ImmutableSet对hashCode()和equals有不同语义。

在可能的情况下避免线性拷贝,可以最大限度地减少防御性编程风格所带来的性能开销。

asList视图

所有不可变集合都有一个asList()方法提供ImmutableList视图,来帮助你用列表形式方便地读取集合元素。例如,你可以使用sortedSet.asList().get(k)从ImmutableSortedSet中读取第k个最小元素。

asList()返回的ImmutableList通常是——并不总是——开销稳定的视图实现,而不是简单地把元素拷贝进List。也就是说,asList返回的列表视图通常比一般的列表平均性能更好,比如,在底层集合支持的情况下,它总是使用高效的contains方法。

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

可变集合接口 属于JDK还是Guava 不可变版本
Collection JDK
List JDK
Set JDK
SortedSet/NavigableSet JDK
Map JDK
SortedMap JDK
Guava
SortedMultiset Guava
Guava
ListMultimap Guava
SetMultimap Guava
Guava
Guava
Guava
文章转自 

转载地址:http://chrfx.baihongyu.com/

你可能感兴趣的文章
[转]struct2 拦截所有没有登录的用户,强行转到登录界面AuthorizationInterceptor
查看>>
html5 手机APP计算高度问题
查看>>
P4139 上帝与集合的正确用法
查看>>
我的Android进阶之旅------>Android中adb install 安装错误常见列表
查看>>
我的Android进阶之旅------>如何解决Android 5.0中出现的警告: Service Intent must be explicit:...
查看>>
计算机网络常考知识点总结
查看>>
C\C++程序员面试宝典---持续整理
查看>>
Linux read line
查看>>
Daily Srum 10.28
查看>>
11G、12C安装结束需要做的一些操作
查看>>
xtrabackup支持的engine
查看>>
4.16 删除重复记录
查看>>
7.02 求某列中的最小、最大值
查看>>
快速查找素数 http://acm.nyist.net/JudgeOnline/problem.php?pid=187
查看>>
(转)Java经典设计模式(3):十一种行为型模式(附实例和详解)
查看>>
swf文件过大
查看>>
php中exec,system等函数的作用
查看>>
链表学习
查看>>
python学习_day1
查看>>
以太网
查看>>