范例

01    public static final ImmutableSet<String> COLOR_NAMES = ImmutableSet.of(
02 "red",
03 "orange",
04 "yellow",
05 "green",
06 "blue",
07 "purple");
08
09 class Foo {
10 Set<Bar> bars;
11 Foo(Set<Bar> bars) {
12 this.bars = ImmutableSet.copyOf(bars); // defensive copy!
13 }
14 }

为什么要使用不可变集合

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

  • 当对象被不可信的库调用时,不可变形式是安全的;
  • 不可变对象被多个线程调用时,不存在竞态条件问题
  • 不可变集合不需要考虑变化,因此可以节省时间和空间。所有不可变的集合都比它们的可变形式有更好的内存利用率(分析和测试细节);
  • 不可变对象因为有固定不变,可以作为常量来安全使用。

创建对象的不可变拷贝是一项很好的防御性编程技巧。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工具,如
1    public static final ImmutableSet<Color> GOOGLE_COLORS =
2 ImmutableSet.<Color>builder()
3 .addAll(WEBSAFE_COLORS)
4 .add(new Color(0, 191, 255))
5 .build();

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

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

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

比想象中更智能的copyOf

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

1    ImmutableSet<String> foobar = ImmutableSet.of("foo", "bar", "baz");
2 thingamajig(foobar);
3
4 void thingamajig(Collection<String> collection) {
5 ImmutableList<String> defensiveCopy = ImmutableList.copyOf(collection);
6 ...
7 }

在这段代码中,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 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

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: [Google Guava] 2.1-不可变集合

[Google Guava] 2.1-不可变集合的更多相关文章

  1. [Google Guava] 2.3-强大的集合工具类:java.util.Collections中未包含的集合工具

    原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collections包含的工具方法.G ...

  2. java代码之美(4)---guava之Immutable(不可变)集合

    Immutable(不可变)集合 一.概述 guava是google的一个库,弥补了java语言的很多方面的不足,很多在java8中已有实现,暂时不展开.Collections是jdk提供的一个工具类 ...

  3. java代码(4)---guava之Immutable(不可变)集合

    Immutable(不可变)集合   一,概述 guava是google的一个库,弥补了java语音的很多方面的不足,很多在java8中已有实现,暂时不展开,Collections是jdk提供的一个工 ...

  4. Guava集合--Immutable(不可变)集合

    所谓不可变集合,顾名思义就是定义了之后不可修改的集合. 一.为什么要使用不可变集合 不可变对象有很多优点,包括: 当对象被不可信的库调用时,不可变形式是安全的: 不可变对象被多个线程调用时,不存在竞态 ...

  5. Guava学习笔记:Immutable(不可变)集合

    不可变集合,顾名思义就是说集合是不可被修改的.集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变. 为什么要用immutable对象?immutable对象有以下的优点: 1.对不可靠的客 ...

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

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

  7. [Google Guava] 强大的集合工具类:java.util.Collections中未包含的集合工具

    转载的,有问题请联系我 原文链接 译文链接 译者:沈义扬,校对:丁一 尚未完成: Queues, Tables工具类 任何对JDK集合框架有经验的程序员都熟悉和喜欢java.util.Collecti ...

  8. Java源码分析:Guava之不可变集合ImmutableMap的源码分析

    一.案例场景 遇到过这样的场景,在定义一个static修饰的Map时,使用了大量的put()方法赋值,就类似这样-- public static final Map<String,String& ...

  9. [Google Guava]学习--新集合类型Multiset

    Guava提供了一个新集合类型Multiset,它可以多次添加相等的元素,且和元素顺序无关.Multiset继承于JDK的Cllection接口,而不是Set接口. Multiset主要方法介绍: a ...

随机推荐

  1. Java基础---Java循环区别

    三种循环的区别. 1. 如果条件判断从来没有满足过,那么for循环和while循环将会执行0次,但是do-while循环会执行至少一次.2. for循环的变量在小括号当中定义,只有循环内部才可以使用. ...

  2. (五)Respose 知识点总结 (来自那些年的笔记)

    目录 HttpServletResponse简介 向客户机写数据 HttpServletResponse应用 打印中文,让浏览器显示不乱码 : 下载文件 输出随机图片(验证码) 不要缓存 图片的src ...

  3. PHP基础之函数

    函数概念: 函数是用来完成某种特定任务的可重用代码块; 函数可以使程序更具模块化,拥有良好的结构; 函数定义后在程序中可以重复调用; 函数分为内置函数和自定义函数 考点: 变量的作用域和静态变量 延伸 ...

  4. 无线网卡SP-WL450U的驱动问题

    修改win10的设备驱动为需要的驱动,SP-WL450U的驱动问题 解决SP-WL450U的驱动问题,在电脑上安装无线网卡后,总是用不上5G信号,只能选择2.4G.重新安装程序后也不行,在反复试用后发 ...

  5. STM32的I2C通讯过程

    使用I2C外设通讯时,在通讯的不同阶段它会对“状态寄存器(SR1 及SR2)”的不同数据位写入参数,通过读取这些寄存器标志来了解通讯状态. 1.主发送器 可使用STM32标准库函数来直接检测这些事件的 ...

  6. 不遮挡人物弹幕是怎么实现的——图片蒙版效果-webkit-mask

    这是一个实验中的功能,用于设置元素上遮罩层的图像. 一.Values none:默认值,透明的黑色图像层,也就是没有遮罩层. <mask-source>:<mask>或CSS图 ...

  7. ubuntu14.04

    14.10显卡驱动有问题 1.恢复启动引导菜单:启动盘 -> 运行到分区之前,不要分区 -> shift+f10 进入dos -> bootsec /fixmbr ->关闭重启 ...

  8. python实现tcp代理

    1.代理流程图 2.实现代码 #! usr/bin/python2 import sys import socket import thread #handle local buffer def re ...

  9. OpenCV实现图象翻转、滤波、锐化

    OpenCV实现图象翻转.滤波.锐化 注:以下代码,使用opencv库函数实现了对图片的翻转.灰度图转换.各种滤波.各种锐化. 库函数相关参数及说明参阅:OpenCV中文站=>opencv教程( ...

  10. 如何让某些用户对Marketing Cloud的contact数据只能实施只读操作

    打开maintain business role这个应用: 创建一个新的business role,然后添加下列这几个catalogs: SAP_CEC_BC_MKT_ADM_PC Marketing ...