Guava是一组来自谷歌的核心Java库,其中包括新的集合类型(好比multimap射和multiset)、不可变集合、并发、I/O、散列、缓存、字符串等的实用工具。它在谷歌中的大多数Java项目中被普遍使用,也被许多其余公司普遍使用html
今天咱们就来看一下Guava的不可变集合(Immutable Collections)java
首先咱们思考一个问题,什么是不可变,咱们知道在Java里面String就是不可变的,为何要设计不可变的类和集合呢?web
你能够先想一想这个问题,再继续往下看编程
对象建立后,全部的状态和属性在整个生命周期内不能被修改缓存
同理,不可变集合就是集合建立后,不能对集合中的对象进行修改安全
好处1:让并发处理变得更简单了数据结构
在并发编程的世界里,最麻烦的问题就是处理多个线程间的资源共享问题,稍不注意就会出现线程间相互影响的问题多线程
并且这种问题排查起来很是困难,不是每次都会出现。并发
通常咱们处理并发问题,都是在共享资源上加锁,好比synchronize、Lock等,让线程串行的来进行处理svg
其实仔细想一下,之全部会有并发的问题,是由于线程之间会进行资源争抢,对共享资源进行修改才会影响到其余线程
那假如共享资源不能被修改,每一个线程获取到的都是同样的,就不存在并发的问题了
想一想是否是?每一个线程获取到的数据都是同样的,并且共享资源不能被任何线程修改,那线程之间根本就不会相互影响,自然就是线程安全的
因此不可变对象的好处之一是不用处理并发状况下的资源竞争问题
好处2:消除了反作用
下面咱们看一个例子
public class DemoTest { public static void main(String[] args){ Student student = new Student(); student.setName("tom"); student.setAge(30); DemoTest demoTest = new DemoTest(); demoTest.validateAge(student); //若是后续要使用Age,极可能不知道Age被改了,容易产生BUG } public boolean validateAge(Student student){ if(student.getAge() > 20){ student.setAge(student.getAge() - 3);//此处对年龄进行了反作用处理 return false; } return true; } } class Student{ private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
那假如Student是不可变对象,建立后属性和状态都不能被改变,就不会出现这种问题了
好处3:不可变对象能够减小集合出错的几率
你们在使用Map的时候,是否是常常以String做为Key,那假如String是可变的对象,想一想会有什么问题?
Map<String,String> map = new HashMap<String,String>(); String key = "hello"; map.put(key,"world");
假如key是可变的对象,可能出现的问题是,当你去经过String对象get数据的时候,有可能Map中Key已经变了
会致使你取不到对象了,一转眼对象没啦~~~ 想一想就可怕~~~
上面咱们说不可变对象有不少好处, 那不可变对象是彻底不可变的吗?
有的人可能就迷惑了
既然设计成不可变对象了,难道你还能把它给变了不成?
看看下面这段代码:
String str = "Hello"; System.out.println("str:" + str); Field value = String.class.getDeclaredField("value"); value.setAccessible(true); char[] arr = (char[]) value.get(str); arr[4] = '_'; System.out.println("str:" + str);
输出结果:
str:Hello str:Hell_
能够看出来,String对象建立后,能够利用反射来进行修改
既然能改变,为什么还叫不可变对象?
这里面你们不要误会不可变的本意,从不可变对象的意义分析能看出来对象的不可变性只是用来辅助帮助你们更简单地去编写代码,减小程序编写过程当中出错的几率,这是不可变对象的初衷。
若是真要靠经过反射来改变一个对象的状态,此时编写代码的人也应该会意识到此类在设计的时候就不但愿其状态被更改,从而引发编写代码的人的注意
以上咱们介绍了不可变对象,下面咱们就看一下Guava中的不可变集合
为何要使用不可变集合?
不可变集合的使用方法
其实JDK中也提供了不可变集合,以下:
List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); List<String> unList = Collections.unmodifiableList(list); unList.add("d");//往不可变List中添加元素会报错
表面上看,也实现了不可变集合,可是我修改原list呢
list.add(d);
此时,能够修改为功,而且不可变unList中的元素也被修改了,没有达到不可变的特性
Guava中不可变集合的使用方法
一、copyOf方法
基于已有的集合建立不可变集合
List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); ImmutableList<String> immutList = ImmutableList.copyOf(list);
咱们能够验证一下上面JDK不可变集合的问题,在原list中增长元素,不可变集合不受影响
list.add("d"); System.out.println(immutList);
输出以下:
[a,b,c]
二、of方法
ImmutableList<String> immutableList = ImmutableList.of("a","b","c");
三、Builder方法
List<String> list = new ArrayList<String>(); list.add("a"); list.add("b"); list.add("c"); ImmutableList<String> immutableList = ImmutableList.<String>builder().addAll(list).add("d").build();
能够看到,Builder方法更像是组合了copyOf和of方法
此处,对于有序的不可变集合来讲,是在集合构造完成时就已经排序完成
ImmutableSortedSet.of("a", "b", "c", "a", "d", "b");
会在构造时把元素排序为a,b,c,d。`
全部不可变集合都有一个asList()方法提供ImmutableList视图,来帮助你用列表形式方便地读取集合元素。例如,你可使用sortedSet.asList().get(k)从ImmutableSortedSet中读取第k个最小元素。
asList()返回的ImmutableList一般是——并不老是——开销稳定的视图实现,而不是简单地把元素拷贝进List。也就是说,asList返回的列表视图一般比通常的列表平均性能更好,好比,在底层集合支持的状况下,它老是使用高效的contains方法。
可变集合类型 | 可变集合源:JDK or Guava? | Guava不可变集合 |
---|---|---|
Collection | JDK | ImmutableCollection |
List | JDK | ImmutableList |
Set | JDK | ImmutableSet |
ImmutableSortedSet | JDK | ImmutableSortedSet |
Map | JDK | ImmutableMap |
Multiset | Guava | ImmutableMultiset |
SortedMultiset | Guava | ImmutableSortedMultiset |
Multimap | Guava | ImmutableMultimap |
ListMultimap | Guava | ImmutableListMultimap |
SetMultimap | Guava | ImmutableSetMultimap |
BiMap | Guava | ImmutableBiMap |
ClassToInstanceMap | Guava | ImmutableClassToInstanceMap |
Table | Guava | ImmutableTable |
参考:
https://www.cnblogs.com/dolphin0520/p/10693891.html
https://blog.51cto.com/kaolaa/1794793
若是感受对你有些帮忙,想跟我一块儿学习,坚信技术改变世界,请关注Java天堂公众号,我会按期分享本身的学习成果,第一时间推送给你