Guava源码学习(三)ImmutableCollection
基于版本:Guava 22.0
0. ImmutableCollection简介
类似于JDK的Collections.unmodifiableXXX,可以创建不可变集合,是一种防御式编程的体现。
1. 类图

这张类图也不完全,ImmutableCollection实际上有十几个子类
2. 设计思路
ImmutableCollection是继承于Collection的抽象类,将所有涉及到修改的方法全部设置为final(禁止子类重写),方法体是直接抛出UnsupportedOperationException。
这样就实现了禁止修改的语义。
随意举两个例子如下:
/**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@CanIgnoreReturnValue
@Deprecated
@Override
public final boolean add(E e) {
throw new UnsupportedOperationException();
} /**
* Guaranteed to throw an exception and leave the collection unmodified.
*
* @throws UnsupportedOperationException always
* @deprecated Unsupported operation.
*/
@CanIgnoreReturnValue
@Deprecated
@Override
public final boolean remove(Object object) {
throw new UnsupportedOperationException();
}
但是如何初始化ImmutableCollection呢?
a. ImmutableCollection的子类都实现了of与copyOf方法,通过这两个方法可以直接获取ImmutableCollection的实例。
b. ImmutableCollection.Builder提供了更加方便的构造器,ImmutableCollection的子类通过实现ImmutableCollection.Builder的关键方法,可以创建ImmutableCollection的实例。
3. ImmutableList
简单分析一下ImmutableList的实现
public static <E> ImmutableList<E> copyOf(Collection<? extends E> elements) {
if (elements instanceof ImmutableCollection) {
@SuppressWarnings("unchecked") // all supported methods are covariant
ImmutableList<E> list = ((ImmutableCollection<E>) elements).asList();
return list.isPartialView() ? ImmutableList.<E>asImmutableList(list.toArray()) : list;
}
return construct(elements.toArray());
}
这个copyOf方法是很有意思的:
如果发现传入的集合是ImmutableCollection,并且不是完全的集合(由subList这种方法创建的集合),则创建一个拷贝(不再保留对原集合的引用,如果原集合很大,可以减少内存泄漏的可能),如果是完全的集合,则直接返回它的引用。
/**
* Returns an immutable list of the elements between the specified {@code
* fromIndex}, inclusive, and {@code toIndex}, exclusive. (If {@code
* fromIndex} and {@code toIndex} are equal, the empty immutable list is
* returned.)
*/
@Override
public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, size());
int length = toIndex - fromIndex;
if (length == size()) {//直接返回整个引用
return this;
} else if (length == 0) {
return of();//返回EMPTY
} else {
return subListUnchecked(fromIndex, toIndex);//创建subList
}
} /**
* Called by the default implementation of {@link #subList} when {@code
* toIndex - fromIndex > 1}, after index validation has already been
* performed.
*/
ImmutableList<E> subListUnchecked(int fromIndex, int toIndex) {
return new SubList(fromIndex, toIndex - fromIndex);//限定subList的范围
} class SubList extends ImmutableList<E> {
final transient int offset;
final transient int length; SubList(int offset, int length) {
this.offset = offset;
this.length = length;
} @Override
public int size() {
return length;
} @Override
public E get(int index) {//转换下标,从原list的对应位置取值
checkElementIndex(index, length);
return ImmutableList.this.get(index + offset);
} @Override
public ImmutableList<E> subList(int fromIndex, int toIndex) {
checkPositionIndexes(fromIndex, toIndex, length);
return ImmutableList.this.subList(fromIndex + offset, toIndex + offset);
} @Override
boolean isPartialView() {//标注这是一个不完整的集合
return true;
}
}
ImmutableList.subList方法的实现,没有创建ImmutableList的副本,而是直接访问原ImmutableList中的元素,当然中间会进行下标的转换。
由于ImmutableList是不可变的,所以这样做是非常安全的,而且节省了开销。
4. 与Collections.unmodifiableXXX的区别
unwieldy and verbose; unpleasant to use everywhere you want to make defensive copies
unsafe: the returned collections are only truly immutable if nobody holds a reference to the original collection
inefficient: the data structures still have all the overhead of mutable collections, including concurrent modification checks, extra space in hash tables, etc.
直接引用并发编程网的翻译如下
笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;
不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;
低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。
Guava源码学习(三)ImmutableCollection的更多相关文章
- mybatis源码学习(三)-一级缓存二级缓存
本文主要是个人学习mybatis缓存的学习笔记,主要有以下几个知识点 1.一级缓存配置信息 2.一级缓存源码学习笔记 3.二级缓存配置信息 4.二级缓存源码 5.一级缓存.二级缓存总结 1.一级缓存配 ...
- Vue源码学习三 ———— Vue构造函数包装
Vue源码学习二 是对Vue的原型对象的包装,最后从Vue的出生文件导出了 Vue这个构造函数 来到 src/core/index.js 代码是: import Vue from './instanc ...
- Guava源码学习(五)EventBus
基于版本:Guava 22.0 Wiki:EventBus 0. EventBus简介 提供了发布-订阅模型,可以方便的在EventBus上注册订阅者,发布者可以简单的将事件传递给EventBus,E ...
- spring源码学习(三)--spring循环引用源码学习
在spring中,是支持单实例bean的循环引用(循环依赖)的,循环依赖,简单而言,就是A类中注入了B类,B类中注入了A类,首先贴出我的代码示例 @Component public class Add ...
- [spring源码学习]三、IOC源码——自定义配置文件读取
一.环境准备 在文件读取的时候,第9步我们发现spring会根据标签的namespace来选择读取方式,联想spring里提供的各种标签,比如<aop:xxx>等应该会有不同的读取和解析方 ...
- Guava源码学习(二)Ordering
基于版本:Guava 22.0 Wiki:Ordering 0. Ordering简介 Guava的Ordering提供了链式风格的比较器的实现,我们可以用Ordering轻松构建复杂的比较器. 1. ...
- Guava源码学习(零)前言
Guava是由Google出品的Java类库,功能强大且易用. 后续我会用多篇博客介绍Guava的使用方法,以及从源码层面分析其实现原理. 分析次序基于Guava的官方Wiki 基于版本:Guava ...
- vue 源码学习三 vue中如何生成虚拟DOM
vm._render 生成虚拟dom 我们知道在挂载过程中, $mount 会调用 vm._update和vm._render 方法,vm._updata是负责把VNode渲染成真正的DOM,vm._ ...
- Guava源码学习(一)Optional
基于版本:Guava 22.0 Wiki:Using and avoiding null 0:Optional简介 null在很多场景下会引发问题,NullPointerException困扰过无数的 ...
随机推荐
- VS Extension+NVelocity系列(三)——让VS支持 NVelocity的智能提示(中)
一.定义 我们知道,我们的插件是服务于NVelocity的,在你的项目当中,对于NVelocity的模板应当有一个统一的文件扩展名,以便于VS在打开指定扩展名的文件后,就能起到具体的作用. 如果我没有 ...
- DOS程序员手册(九)
第14章参考手册概述 本书余下的章节将向读者们介绍BIOS.DOS各种各样API函数和服务,作为一名程 序员,了解和掌握这些知识是很有好处的.在所介绍的参考手册中,每部手册都汇集了大 量的资源 ...
- SSTI注入绕过(沙盒逃逸原理一样)
在python沙盒逃逸中绕过道理是一样的. 1.python沙盒中删除了很多模块,但是没有删除reload reload(__builtins__),重新加载被删除的模块,直接命令执行,只用于py2 ...
- 浅谈 css 之 position用法
在 css中, position 属性有四个值可用: static(默认值).absolute.relative.fixed. relative:相对定位(相对于自身进行在常规流中的位置进行定位,保留 ...
- python之if测试
(一)python的条件判断语句一般格式如下: if (条件1): (执行结果) elif(条件2): (执行结果) ..... else: (执行结果) 执行顺序为从上到下判断,若条件1不符合则进入 ...
- VB.NET视频总结——后续篇
上篇基础总结简单介绍了前几个单元的主要内容和理解的思路,这篇介绍后几个单元的内容,主要介绍了应用程式的设计与部署方面的内容. 首先,第十一单元讲的是应用程式设计的基础,主要讲解了元件的相关知识.应用程 ...
- 文明距离(civil)
文明距离(civil) 题目描述 你被一个一向箔打中了,现在你掉到了一个一维空间中,也就是一个数轴上. 在这个数轴上,每秒会在一段连续的区间上出现“文明”.而你在每一秒开始的时候,可以花费x的代价移动 ...
- spring in action 学习笔记十四:用纯注解的方式实现spring mvc
在讲用纯注解的方式实现springmvc之前先介绍一个类:AbstractAnnotationDispatcherServletInitializer.这个类的作用是:任何一个类继承AbstractA ...
- hadoop学习之HDFS
1.什么是大数据?什么是云计算?什么是hadoop? 大数据现在很火,到底什么是大数据,多大的数据才算大,一般而言对于TB级以上的数据我们成为大数据,对于这些数据它的价值在哪?大数据的价值就是我们大量 ...
- 母函数(Generation Function) 入门 + 模板
转自:母函数 入门 + 模板 感谢 在数学中,某个序列的母函数(Generating function,又称生成函数)是一种形式幂级数,其每一项的系数可以提供关于这个序列的信息.使用母函数解决问题的 ...