当前位置: 首页 > news >正文

[Google Guava] 2.1-不可变集合

原文链接 译者:沈义扬

范例

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”

怎么使用不可变集合

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

  • copyOf方法,如ImmutableSet.copyOf(set);
  • of方法,如ImmutableSet.of(“a”, “b”, “c”)或 ImmutableMap.of(“a”, 1, “b”, 2);
  • Builder工具,如
public static final ImmutableSet<Color> GOOGLE_COLORS =
        ImmutableSet.<Color>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<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)会试图对如下情况避免线性时间拷贝:

  • 在常量时间内使用底层数据结构是可能的——例如,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不可变版本
CollectionJDKImmutableCollection
ListJDKImmutableList
SetJDKImmutableSet
SortedSet/NavigableSetJDKImmutableSortedSet
MapJDKImmutableMap
SortedMapJDKImmutableSortedMap
MultisetGuavaImmutableMultiset
SortedMultisetGuavaImmutableSortedMultiset
MultimapGuavaImmutableMultimap
ListMultimapGuavaImmutableListMultimap
SetMultimapGuavaImmutableSetMultimap
BiMapGuavaImmutableBiMap
ClassToInstanceMapGuavaImmutableClassToInstanceMap
TableGuavaImmutableTable

 

 

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

转载于:https://www.cnblogs.com/Luwak90/p/9850488.html

相关文章:

  • I/O复用模型详解(网络总结)
  • [ARC066F]Contest with Drinks Hard
  • 5.0中redis-cli的集群管理测试
  • linux基础学习【10】
  • 北京博派通达科技有限公司(前端面试题) 给需要的人
  • IT界提问的艺术
  • hadoop生态搭建(3节点)-15.Nginx_Keepalived_Tomcat配置
  • Hadoop在安装snappy过程中的问题
  • localStorage和sessionStorage
  • 驻波比
  • 【Python】多进程#181101
  • 使用前端开发工具包WijmoJS - 创建自定义DropDownTree控件(包含源代码)
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • java 运算符,流程控制语句,键盘录入
  • 【转】在Win7的IIS上搭建FTP服务及用户授权
  • 【162天】黑马程序员27天视频学习笔记【Day02-上】
  • 230. Kth Smallest Element in a BST
  • 77. Combinations
  • Fastjson的基本使用方法大全
  • Node.js 新计划:使用 V8 snapshot 将启动速度提升 8 倍
  • Sublime Text 2/3 绑定Eclipse快捷键
  • VUE es6技巧写法(持续更新中~~~)
  • 包装类对象
  • 从零搭建Koa2 Server
  • 配置 PM2 实现代码自动发布
  • 深入浅出Node.js
  • 学习笔记:对象,原型和继承(1)
  • 用jQuery怎么做到前后端分离
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • #使用清华镜像源 安装/更新 指定版本tensorflow
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (1) caustics\
  • (4)STL算法之比较
  • (C语言)共用体union的用法举例
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (Redis使用系列) Springboot 使用Redis+Session实现Session共享 ,简单的单点登录 五
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)计算机毕业设计ssm-Java网名推荐系统
  • (算法)N皇后问题
  • (已解决)什么是vue导航守卫
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)关于pipe()的详细解析
  • *1 计算机基础和操作系统基础及几大协议
  • *Django中的Ajax 纯js的书写样式1
  • .halo勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET 程序如何获取图片的宽高(框架自带多种方法的不同性能)
  • .NET/C# 在代码中测量代码执行耗时的建议(比较系统性能计数器和系统时间)
  • .netcore 6.0/7.0项目迁移至.netcore 8.0 注意事项
  • .net流程开发平台的一些难点(1)
  • .Net转前端开发-启航篇,如何定制博客园主题
  • .net最好用的JSON类Newtonsoft.Json获取多级数据SelectToken
  • ??eclipse的安装配置问题!??
  • @Autowired多个相同类型bean装配问题
  • @KafkaListener注解详解(一)| 常用参数详解
  • [ C++ ] STL_vector -- 迭代器失效问题