java代码(4)---guava之Immutable(不可变)集合

时间:2021-02-21 05:32:20

    Immutable(不可变)集合


 

一,概述

  guava是google的一个库,弥补了java语音的很多方面的不足,很多在java8中已有实现,暂时不展开,Collections是jdk提供的一个工具类

  Guava中不可变对象和Collections工具类的unmodifiableSet/List/Map/etc的区别:

 当Collections创建的不可变集合的wrapper类改变的时候,不可变集合也会改变,而Guava的Immutable集合保证确实是不可变的。

1、jdk中实现immutable集合

在jdk中提供了Collections.unmodifiableXXX系列方法来实现不可变集合,但是存在一些问题,下面我们先看一个具体案例

  

public class ImmutableTest {

    @Test
public void testJDKImmutable(){
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c"); //通过list创建一个不可变的unmodifiableList集合
List<String> unmodifiableList=Collections.unmodifiableList(list);
System.out.println(unmodifiableList); //通过list添加元素
list.add("ddd");
System.out.println("往list添加一个元素:"+list);
System.out.println("通过list添加元素之后的unmodifiableList:"+unmodifiableList); //通过unmodifiableList添加元素
unmodifiableList.add("eee");
System.out.println("往unmodifiableList添加一个元素:"+unmodifiableList); }
}

运行结果:

java代码(4)---guava之Immutable(不可变)集合

从运行结果中可以看出:虽然unmodifiableList不可以直接添加元素,但是我的list是可以添加元素的,而list的改变也会使unmodifiableList改变。

所以说Collections.unmodifiableList实现的不是真正的不可变集合

2、Guava的immutable集合

  Guava提供了JDK里标准集合类里的immutable版本的简单方便的实现,以及Guava自己的一些专门集合类的immutable实现,当你不希望修改一个集合类,

或者想做一个常量集合类的时候,使用immutable集合类就是一个最佳的编程实践

注意:每个Guava immutable集合类的实现都拒绝null值,我们做过对Google内部代码的全面的调查,并且发现只有5%的情况下集合类允许null值,而95%的情况下

都拒绝null值,万一真的需要能接受null值得集合类,你可以考虑用Collections.unmodifiableXXX。

immutable集合可以有以下几种方式来创建:

  1、用copyOf方法,譬如,ImmutableSet.copyOf(set)

  2、使用of方法,譬如,ImmutableSet.of("a","b","c")或者ImmutableMap.of("a",1,"b",2)

  3、使用Builder类

举例:

@Test
public void testGuavaImmutable(){ List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c"); ImmutableList<String> imlist=ImmutableList.copyOf(list);
System.out.println("imlist:"+imlist); ImmutableList<String> imOflist=ImmutableList.of("peida","jerry","harry");
System.out.println("imOflist:"+imOflist); ImmutableSortedSet<String> imSortList=ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
System.out.println("imSortList:"+imSortList); list.add("baby");
//关键看这里是否imlist也添加新元素了
System.out.println("list添加新元素之后看imlist:"+imlist); ImmutableSet<Color> imColorSet =
ImmutableSet.<Color>builder()
.add(new Color(0, 255, 255))
.add(new Color(0, 191, 255))
.build(); System.out.println("imColorSet:"+imColorSet);
}

运行结果,发现imList并未改变

java代码(4)---guava之Immutable(不可变)集合

对于排序的集合来说有例外,因为元素的顺序在构建集合的时候就被固定下来了,譬如ImmutableSet.of("a","b","c","a","d","b")对于这个集合的遍历顺序来说就是"a","b","c","d"

更智能的copyOf

copyOf方法比你想的更智能,ImmutableXXX.copyOf会在合适的情况下避免拷贝元素的操作,先忽略具体的细节,但是它的实现一般都是很"智能",譬如:

@Test
public void testCotyOf(){
ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
System.out.println("imSet:"+imSet); //set直接转list
ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
System.out.println("imlist:"+imlist); //list直接转SortedSet
ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
System.out.println("imSortSet:"+imSortSet); List<String> list=new ArrayList<String>();
for(int i=0;i<=10;i++){
list.add(i+"x");
}
System.out.println("list:"+list); //截取集合部分元素
ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 8));
System.out.println("imInfolist:"+imInfolist);
}

运行结果:

java代码(4)---guava之Immutable(不可变)集合

java代码(4)---guava之Immutable(不可变)集合