博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Guava源码学习(三)ImmutableCollection
阅读量:5145 次
发布时间:2019-06-13

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

基于版本:

Wiki:

 

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 
ImmutableList
copyOf(Collection
elements) { if (elements instanceof ImmutableCollection) { @SuppressWarnings("unchecked") // all supported methods are covariant ImmutableList
list = ((ImmutableCollection
) elements).asList(); return list.isPartialView() ? ImmutableList.
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
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
subListUnchecked(int fromIndex, int toIndex) { return new SubList(fromIndex, toIndex - fromIndex);//限定subList的范围 } class SubList extends ImmutableList
{ 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
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.

直接引用如下

  • 笨重而且累赘:不能舒适地用在所有想做防御性拷贝的场景;
  • 不安全:要保证没人通过原集合的引用进行修改,返回的集合才是事实上不可变的;
  • 低效:包装过的集合仍然保有可变集合的开销,比如并发修改的检查、散列表的额外空间,等等。

 

转载于:https://www.cnblogs.com/stevenczp/p/7274240.html

你可能感兴趣的文章
POJ 2891
查看>>
qt+opencv 构建项目时报错——no such file or directory
查看>>
uva 1589
查看>>
mysql in(...) 1次取出当前记录及上1条下1条记录, 且使用了主键作为索引
查看>>
java实现计算器
查看>>
周五——3.15
查看>>
转载 调试器工作原理
查看>>
软工作业-wc(Python实现)
查看>>
蛇形填数
查看>>
php 两段文本对比,不同的文字显示高亮
查看>>
B-tree多路搜索树
查看>>
Swarm基于多主机容器网络 (overlay networks ) - 运维笔记
查看>>
基于嵌入式操作系统VxWorks的多任务并发程序设计(1)――基本概念 分类: ...
查看>>
数字视频基础(四) 分类: 生活百科 2014...
查看>>
am335x在ubuntu下使用StarterWare编写裸机程序并在CCS中用Jlink调试 ...
查看>>
VS2005 添加onTimer定时器
查看>>
nodejs, 遍历所有进程, 且关闭匹配的进程
查看>>
STP总结
查看>>
Android 开发 VectorDrawable 矢量图 (三)矢量图动画
查看>>
maven入门教程
查看>>