版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/SunnyYoona/article/details/71080164

不可变集合,顾名思义就是说集合是不可被修改的。集合的数据项是在创建的时候提供,并且在整个生命周期中都不可改变。

1. UnmodifiableXXX

JDK提供了UnmodifiableXXX(Collections.unmodifiable)用于生成不可变容器。不可变容器无法修改返回容器的内容。但是这里值的是无法通过set或add方法修改容器内的reference的指向,而不是禁止reference指向内容的修改。

public static void test1(){List<User> list = Lists.newArrayList(new User());list.get(0).setName("yoona");list.get(0).setCompany("quanr");List<User> unmodifiableList = Collections.unmodifiableList(list);System.out.println(unmodifiableList.get(0).getName()); //yoonaunmodifiableList.get(0).setName("sjf");//unmodifiableList.add(new User());//unmodifiableList.remove(0);System.out.println(unmodifiableList.get(0).getName()); //sjf
}

Collections.unmodifiableXXX返回的是原容器的视图。虽然无法对返回容器进行修改,但是对原容器的修改,会影响返回容器的内容。

容器内容的变更也会通过视图展现出来:

public static void test2(){User user = new User();user.setName("yoona");user.setCompany("quanr");List<User> list = Lists.newArrayList(user);List<User> unmodifiableList = Collections.unmodifiableList(list);// 对原容器的修改User user2 = new User();user2.setName("sjf");list.add(user2);// 影响返回容器System.out.println(unmodifiableList.get(1).getName()); //sjf}

2. ImmutableXXX

2.1 说明

(1)提供了不可修改容器的功能,保证返回的容器不能被调用者修改,并且原容器的修改也不会影响ImmutableXXX。这一点与UnmodifiableXXX不同。

(2)对不可靠的客户代码来说,它使用安全,可以在未受信任的类库中安全的使用这些对象。

(3)线程安全的,Immutable对象在多线程下安全,没有竟态条件。

(4)不需要支持可变性,可以尽量节省空间和时间的开销。所有的不可变集合实现都比可变集合更加有效的利用内存。

(5)可以被使用为一个常量,并且期望在未来也是保持不变的。

2.2 原理

返回的对象不是原容器的视图,而是原容器的一份拷贝。

public static final void test1(){User user = new User();user.setName("Yoona");List<User> list = Lists.newArrayList(user);ImmutableList<User> immutableList = ImmutableList.copyOf(list);User user2 = new User();user2.setName("sjf");list.add(user2);System.out.println(immutableList.size()); // 1}

3.源码

3.1 Builder
public abstract static class Builder<E> {static final int DEFAULT_INITIAL_CAPACITY = 4;/*** 扩容* @param oldCapacity* @param minCapacity* @return*/static int expandedCapacity(int oldCapacity, int minCapacity) {if (minCapacity < 0) {throw new AssertionError("cannot store more than MAX_VALUE elements");}// careful of overflow!int newCapacity = oldCapacity + (oldCapacity >> 1) + 1;if (newCapacity < minCapacity) {newCapacity = Integer.highestOneBit(minCapacity - 1) << 1;}if (newCapacity < 0) {newCapacity = Integer.MAX_VALUE;}return newCapacity;}Builder() {}/*** 这是一个抽象方法,添加元素到集合中,具体怎么添加取决于是什么样的集合。具体的实现由ImmutableCollection子类实现* @param element 待添加的元素* @throws  element为null 抛出空指针异常*/public abstract Builder<E> add(E element);/*** 使用了可变长参数,添加多个element元素到集合中。* 每个生成器类重写此方法,以返回其自己的类型。* @param elements* @throws 如果elements为null,或者包含一个元素为null都会抛出空指针异常*/public Builder<E> add(E... elements) {for (E element : elements) {add(element);}return this;}/*** 使用了迭代器Iterable,添加Iterable中的element元素到集合中。* 每个生成器类重写此方法,以返回其自己的类型。* @param elements* @throws 如果elements为null,或者包含一个元素为null都会抛出空指针异常*/public Builder<E> addAll(Iterable<? extends E> elements) {for (E element : elements) {add(element);}return this;}/*** 使用了迭代器Iterator,添加Iterator中的element元素到集合中。* 每个生成器类重写此方法,以返回其自己的类型。* @param elements* @throws 如果elements为null,或者包含一个元素为null都会抛出空指针异常*/public Builder<E> addAll(Iterator<? extends E> elements) {while (elements.hasNext()) {add(elements.next());}return this;}/*** 抽象方法,由具体实现类返回相应类型的ImmutableCollection* @return*/public abstract ImmutableCollection<E> build();}
3.2 copyIntoArray(Object[] dst,int offset)

复制不可变集合中内容到指定数组dst的指定位置offset。返回最新的偏移量。

int copyIntoArray(Object[] dst, int offset) {for (E e : this) {dst[offset++] = e;}return offset;}
3.3 Object[] toArray()

不可变集合转变为Object数组。如果不可变集合的长度为0,返回一个空的Object数组。

Object[] EMPTY_ARRAY = new Object[0];

如果不可变集合的长度不为0,使用上面提到的copyIntoArray()函数拷贝到一个新的Object数组。

public final Object[] toArray() {int size = size();if (size == 0) {return ObjectArrays.EMPTY_ARRAY;}Object[] result = new Object[size];copyIntoArray(result, 0);return result;}
3.4 boolean add(E e)

当试图为一个不可变集合添加元素时,抛出UnsupportedOperationException异常,表示不可变集合不支持添加元素操作,从而保证集合的不可修改性。

public final boolean add(E e) {throw new UnsupportedOperationException();}
3.5 boolean remove(Object object)

当试图从一个不可变集合删除元素时,抛出UnsupportedOperationException异常,表示不可变集合不支持删除元素操作,从而保证集合的不可修改性。

@Deprecated@Overridepublic final boolean remove(Object object) {throw new UnsupportedOperationException();}

同理,也不支持多个元素的添加与删除操作,都会抛出UnsupportedOperationException异常。

@Deprecated@Overridepublic final boolean addAll(Collection<? extends E> newElements) {throw new UnsupportedOperationException();}@Deprecated@Overridepublic final boolean removeAll(Collection<?> oldElements) {throw new UnsupportedOperationException();}
3.6 UnmodifiableIterator<E> iterator()

通过集合获取不可变性迭代器UnmodifiableIterator。这是一个抽象方法,具体实现看具体的继承类。

@Overridepublic abstract UnmodifiableIterator<E> iterator();
3.7 ImmutableList<E> asList() 与 createAsList()

从集合得到不可变性链表ImmutableList,具体为啥在ImmutableCollection中写此方法还没明白。

public ImmutableList<E> asList() {ImmutableList<E> list = asList;return (list == null) ? (asList = createAsList()) : list;}ImmutableList<E> createAsList() {switch (size()) {case 0:return ImmutableList.of();case 1:return ImmutableList.of(iterator().next());default:return new RegularImmutableAsList<E>(this, toArray());}}

[Guava源码日报](8)ImmutableCollection相关推荐

  1. [Guava源码日报(1)]Guava类库简介

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/SunnyYoona/article/details/50805613 1. 简介 Guava工程包含 ...

  2. Guava 源码分析(Cache 原理)

    作者:crossoverJie's Blog 来源:https://crossoverjie.top/2018/06/13/guava/guava-cache/ 前言 Google 出的 Guava  ...

  3. Guava源码分析——Immutable Collections(4)

    Immutable的集合体系,还有中很重要的集合没有介绍,就是ImmutableMap,通过UML图,可以看出ImmutableMap的结构体系. 首先来看一下ImmutableBiMap,因为普通I ...

  4. Guava源码阅读计划:primitives.Ints

    com.google.common.primitives:八种原始类型和无符号类型的静态工具包 //在java8中可以被Integer.BYTES替代,代表字节数bytespublic static ...

  5. 数据库中间件 Sharding-JDBC 源码分析 —— SQL 执行

    摘要: 原创出处 http://www.iocoder.cn/Sharding-JDBC/sql-execute/ 「芋道源码」欢迎转载,保留摘要,谢谢! 本文主要基于 Sharding-JDBC 1 ...

  6. RateLimiter 源码分析(Guava 和 Sentinel 实现)

    点击上方"方志朋",选择"设为星标" 做积极的人,而不是积极废人 作者javadoop,资深Java工程师 原文链接https://www.javadoop.c ...

  7. Guava RateLimiter限流源码解析和实例应用

    2019独角兽企业重金招聘Python工程师标准>>> 在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是 ...

  8. [轮子系列]Google Guava之CharMatcher源码分析

    本文源地址:http://www.fullstackyang.com/...,转发请注明该地址或segmentfault地址,谢谢! 最近遇到了一些字符匹配的需求,进而仔细地看了CharMatcher ...

  9. 基于MVVM的知乎日报应用安卓源码

    使用data binding , dagger2 , retrofit2和rxjava实现的,基于MVVM的知乎日报APP 运行效果: <ignore_js_op>  使用说明: 项目结构 ...

最新文章

  1. 推荐8个舍不得分享的实用软件和网站,解决很多需求
  2. android jack log,Android:JACK编译错误汇总及解决
  3. [转载] 晓说——第2期:汉人无音乐都怪老祖宗
  4. import和from...import
  5. CI/CD with drone
  6. python获取输入法状态_Python学习中常见的错误
  7. datagrid如何获取一行数据中的某个字段值_SQL中常见的面试题
  8. 少儿故事:小乌鸦智斗老鹰
  9. python批量ping脚本_Python多线程批量Ping主机IP的脚本
  10. 测试人必备实用技能:写出一份好的Bug报告
  11. Linux防火墙配置入门
  12. 2018.09.23 bzoj1076: [SCOI2008]奖励关(期望+状压dp)
  13. BN层详解(含有公式推导过程)
  14. oracle数据库的增删改查
  15. Python系列 之 ReportLab库 pdfgen模块Canvas对象绘制图形和文本
  16. 测试——Bug的生命周期,生命周期流程图
  17. 解决win10桌面无法删除ie浏览器图标
  18. SPI 总线3-line、4-line的定义
  19. 前端框架vue3的node安装及项目构建的4种方法
  20. 什么样的项目算是成功的?项目目标有什么特点?

热门文章

  1. 在vb中实现真正锁定的带自定义菜单的文本控件
  2. 华为云回答2018:AI差异化初见成效,已吹响进攻号角
  3. 50张图片做出李飞飞数万张的效果,类脑AI竟然这样玩?
  4. 英国莽汉司机认罪:放任特斯拉自动驾驶,自己躺在副驾悠哉悠哉
  5. Innodb中常见SQL语句设置的锁类型
  6. 达拉草201771010105《面向对象程序设计(java)》第十七周学习总结
  7. [EasyHexo 专栏] #1 - Markdown 编辑器推荐与语法简介
  8. 《Java8实战》-第十章笔记(用Optional取代null)
  9. 用 :focus-within 实现纯 CSS 下拉框组件
  10. 老王讲设计模式(三)——单例模式