什么是Immutable
不可变集合,顾名思义就是说集合是不可被修改的。集合的数据项在创建的时候提供,并且在整个生命周期中都不可改变。为什么要用immutable对象?
线程安全的:immutable对象在多线程下安全
不需要支持可变性, 可以尽量节省空间和时间的开销. 所有的不可变集合实现都比可变集合更加有效的利用内存
可以被使用为一个常量,并且期望在未来也是保持不变的
jdk中的不可变集合API
在JDK中提供了Collections.unmodifiableXXX系列方法来实现不可变集合, 但是存在一些问题,下面我们先看一个具体实例:public static void testUnmodifiableList(){
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println(list);
List<String> unmodifiableList=Collections.unmodifiableList(list);
System.out.println(unmodifiableList);
List<String> unmodifiableList1=Collections.unmodifiableList(Arrays.asList("a","b","c"));
System.out.println(unmodifiableList1);
String temp=unmodifiableList.get(1);
System.out.println("unmodifiableList [0]:"+temp);
list.add("baby");
System.out.println("list add a item after list:"+list);
System.out.println("list add a item after unmodifiableList:"+unmodifiableList);
unmodifiableList1.add("bb");
System.out.println("unmodifiableList add a item after list:"+unmodifiableList1);
unmodifiableList.add("cc");
System.out.println("unmodifiableList add a item after list:"+unmodifiableList);
}
输出日志:
[a, b, c]
[a, b, c]
[a, b, c]
unmodifiableList [0]:b
list add a item after list:[a, b, c, baby]
list add a item after unmodifiableList:[a, b, c, baby]
Exception in thread "main" java.lang.UnsupportedOperationException
at java.util.Collections$UnmodifiableCollection.add(Unknown Source)
at com.meizu.tv.app.web.stats.Test.testUnmodifiableList(Test.java:44)
at com.meizu.tv.app.web.stats.Test.main(Test.java:16)
说明:Collections.unmodifiableList实现的不是真正的不可变集合,当原始集合修改后,不可变集合也发生变化。不可变集合不可以修改集合数据,当强制修改时会报错,实例中的最后两个add会直接抛出不可修改的错误。
而且效率低,因为它返回的数据结构本质仍旧是原来的集合类,所以它的操作开销,包括并发下修改检查和原来的集合是一样的。
源码分析:
final List list;
UnmodifiableList(List list1)
{
super(list1);
list = list1;
}
public boolean add(Object obj)
{
throw new UnsupportedOperationException();
}
public boolean remove(Object obj)
{
throw new UnsupportedOperationException();
}
Guava的immutable集合
一个immutable集合可以有以下几种方式来创建:(1)用copyOf方法, 譬如, ImmutableSet.copyOf(set)
(2)使用of方法,譬如,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)
(3)使用Builder类
List<String> list=new ArrayList<String>();
list.add("a");
list.add("b");
list.add("c");
System.out.println("list:"+list);
ImmutableList<String> imlist=ImmutableList.copyOf(list);
System.out.println("imlist:"+imlist);
imlist.add("D");
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");
System.out.println("list add a item after list:"+list);
System.out.println("list add a item after 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);
输出:
list:[a, b, c]
imlist:[a, b, c]
imOflist:[peida, jerry, harry]
imSortList:[a, b, c, d]
list add a item after list:[a, b, c, baby]
list add a item after imlist:[a, b, c]
imColorSet:[java.awt.Color[r=0,g=255,b=255], java.awt.Color[r=0,g=191,b=255]]
源码分析:
public static ImmutableList copyOf(Collection elements)
{
if(elements instanceof ImmutableCollection)
{
ImmutableList list = ((ImmutableCollection)elements).asList();
return list.isPartialView() ? asImmutableList(list.toArray()) : list;
} else
{
return construct(elements.toArray());
}
}
java.util.Map.Entry entries[] = (java.util.Map.Entry[])map.entrySet().toArray(EMPTY_ENTRY_ARRAY);
从上面就可以看出ImmutableCollection是把集合中的内容取出来再封装一次,这就解释了为什么可以是Immutable。