文档章节

Guava的不可变集合

d
 debugable
发布于 2016/11/02 17:53
字数 1238
阅读 24
收藏 0

一、不可变集合的优点

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

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

创建对象的不可变拷贝是一项很好的防御性编程技巧。Guava为所有JDK标准集合类型和Guava新集合类型都提供了简单易用的不可变版本。

摘自:http://ifeve.com/google-guava-immutablecollections/

二、创建不可变集合

1.使用of方法

如:I

mmutableList<String> ilist = ImmutableList.of("a","b","c","d","e");

2.使用copyOf

如:

List<String> slist = new ArrayList<String>(20);

slist.add("a");

slist.add("b");

slist.add("c");

slist.add("d");

slist.add("e");

//通过已有List创建不可变list

ImmutableList<String> ilist = ImmutableList.copyOf(slist);

3.使用Builder工具

如:

List<String> slist = new ArrayList<String>(20);

slist.add("a");

slist.add("b");

slist.add("c");

slist.add("d");

slist.add("e");

ImmutableList<String> ilist = ImmutableList.<String>builder().addAll(list).build();

三、如何实现不可变

1.对不可变集合调用addAll、add、set、remove都会抛出UnsupportedOperationException异常

如下是ImmutableList类的源码:

/**

* Guaranteed to throw an exception and leave the list unmodified.

*

* @throws UnsupportedOperationException always

* @deprecated Unsupported operation.

*/

@CanIgnoreReturnValue

@Deprecated

@Override

public final boolean addAll(int index, Collection<? extends E> newElements) {

throw new UnsupportedOperationException();

}

 

/**

* Guaranteed to throw an exception and leave the list unmodified.

*

* @throws UnsupportedOperationException always

* @deprecated Unsupported operation.

*/

@CanIgnoreReturnValue

@Deprecated

@Override

public final E set(int index, E element) {

throw new UnsupportedOperationException();

}

 

/**

* Guaranteed to throw an exception and leave the list unmodified.

*

* @throws UnsupportedOperationException always

* @deprecated Unsupported operation.

*/

@Deprecated

@Override

public final void add(int index, E element) {

throw new UnsupportedOperationException();

}

 

/**

* Guaranteed to throw an exception and leave the list unmodified.

*

* @throws UnsupportedOperationException always

* @deprecated Unsupported operation.

*/

@CanIgnoreReturnValue

@Deprecated

@Override

public final E remove(int index) {

throw new UnsupportedOperationException();

}

 

2.集合中存储的可变对象仍可改变

Users[] arr = new Users[3];

arr[0] = new Users();

arr[0].setId(1);//id=1

arr[1] = new Users();

arr[1].setId(2);

arr[2] = new Users();

arr[2].setId(3);

//copyof 是浅拷贝,因此集合中存放可变对象时,原对象的属性修改了,集合中对象的属性也会修改

ImmutableList<Users> alist = ImmutableList.copyOf(arr);

arr[0].setId(5);

System.out.println(alist.get(0).getId());//id=5

 

四、源码中有趣的地方

不可变集合可以通过of方法来创建,of方法是包含12个重载方法如下:

@SuppressWarnings("unchecked")

public static <E> ImmutableList<E> of() {

return (ImmutableList<E>) EMPTY;

}

 

public static <E> ImmutableList<E> of(E element) {

return new SingletonImmutableList<E>(element);

}

 

public static <E> ImmutableList<E> of(E e1, E e2) {

return construct(e1, e2);

}

 

public static <E> ImmutableList<E> of(E e1, E e2, E e3) {

return construct(e1, e2, e3);

}

 

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4) {

return construct(e1, e2, e3, e4);

}

 

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5) {

return construct(e1, e2, e3, e4, e5);

}

 

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6) {

return construct(e1, e2, e3, e4, e5, e6);

}

 

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7) {

return construct(e1, e2, e3, e4, e5, e6, e7);

}

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8) {

return construct(e1, e2, e3, e4, e5, e6, e7, e8);

}

public static <E> ImmutableList<E> of(E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9) {

return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9);

}

public static <E> ImmutableList<E> of(

E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10) {

return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10);

}

 

public static <E> ImmutableList<E> of(

E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11) {

return construct(e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, e11);

}

 

// These go up to eleven. After that, you just get the varargs form, and

// whatever warnings might come along with it. :(

 

@SafeVarargs // For Eclipse. For internal javac we have disabled this pointless type of warning.

public static <E> ImmutableList<E> of(

E e1, E e2, E e3, E e4, E e5, E e6, E e7, E e8, E e9, E e10, E e11, E e12, E... others) {

Object[] array = new Object[12 + others.length];

array[0] = e1;

array[1] = e2;

array[2] = e3;

array[3] = e4;

array[4] = e5;

array[5] = e6;

array[6] = e7;

array[7] = e8;

array[8] = e9;

array[9] = e10;

array[10] = e11;

array[11] = e12;

System.arraycopy(others, 0, array, 12, others.length);

return construct(array);

}

 

java方法是支持可变参数的,完全可以写成,public static <E> ImmutableList<E> of(E... others);这样实现的原因大神在注释中给出了,为了避免调用者处理类型检测警告。

当方法声明为泛型可变参数时,调用该方法时,编译器就会提示该警告,在JDK1.6之前,可以在方法调用的地方添加@SuppressWarnings("unchecked")注解,但这样比较麻烦,项目组每个调用的地方都需要处理,当然也可以忽略这个问题。

此处ImmutableList中of方法的12个重载的前11个就是为了尽量减少类型检测警告,大神还是很贴心滴为我们写了11个重载,而第12个方法通过JDK1.7的新注解@SafeVarargs 来避免类型检测警告。

@SafeVarargs的用法请参考:http://book.51cto.com/art/201205/339154.htm

© 著作权归作者所有

d

debugable

粉丝 1
博文 5
码字总数 1590
作品 0
昌平
程序员
私信 提问
【java代码之美】---guava之Immutable(不可变)集合

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

雨点的名字
2018/08/02
0
0
Guava集合-不可变集合

JDK的Collections.unmodifiableXXX方法实现不可变集合的一些问题:   1.它用起来笨拙繁琐你不得不在每个防御性编程拷贝的地方用这个方法   2.它不安全:如果有对象reference原始的被封装...

Kevin-air
2016/08/04
12
0
Guava学习笔记:Immutable(不可变)集合

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

pior
2015/03/31
0
0
java中Final关键字和Immutable Class以及Guava的不可变对象

大纲 写这篇文章的起因 java中Final关键字 如何构建不可变对象 Guava中不可变对象和Collections工具类的unmodifiableSet/List/Map/etc的区别 实验代码 写这篇文章的起因 java项目在使用FindB...

敲代码猥琐男
2015/09/23
1K
0
Java不可变ArrayList

集合类在Java中是引用类型,在操作的时候可能不经意间被程序修改,一些初级开发经常会犯类似的错误。这里我们讨论下如何让ArrayList不可改变。本文将演示以下几种方式: JDK Guava Apache C...

艾贺
2018/09/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

聊聊中国的通信行业:从“七国八制”到“中华”脊梁

本期文章和大家一起来聊一聊我曾经从事过的通信行业吧。最近各方面信息的泛滥,包括和华为的同学聊天,自己确实也感慨颇多。想想我自己本科主修通信工程,研究生再修信息与通信工程,从本科开...

CodeSheep
今天
4
0
MDK:ARM M451M:exceed the range of code meory, continue to erase or not?

问题: 代码空间超限 几天前就遇到:exceed the range of code meory, continue to erase or not? 如下所示: 解决过程 开始以为中MDK软件的128KB限制,如是就不能生成HEX文件,应该链接时有提...

SamXIAO
今天
1
1
OSChina 周六乱弹 —— 因违反《中华人民共和国治安管理处罚法》第四十四条之规定

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @xiaoshiyue :#今日歌曲推荐# 惊艳分享谷微的单曲《安守本份》(@网易云音乐) 《安守本份》- 谷微 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
今天
367
9
Angular 英雄编辑器

应用程序现在有了基本的标题。 接下来你要创建一个新的组件来显示英雄信息并且把这个组件放到应用程序的外壳里去。 创建英雄组件 使用 Angular CLI 创建一个名为 heroes 的新组件。 ng gener...

honeymoose
今天
8
0
Kernel DMA

为什么会有DMA(直接内存访问)?我们知道通常情况下,内存数据跟外设之间的通信是通过cpu来传递的。cpu运行io指令将数据从内存拷贝到外设的io端口,或者从外设的io端口拷贝到内存。由于外设...

yepanl
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部