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); } }
運行結果:
通過運行結果我們可以看出:雖然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並未改變。
對於排序的集合來說有例外,因為元素的順序在構建集合的時候就被固定下來了。譬如,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); }
運行結果
Guava集合和不可變對應關系
可變集合類型 | 可變集合源:JDK or Guava? | Guava不可變集合 |
Collection | JDK | ImmutableCollection |
List | JDK | ImmutableList |
Set | JDK | ImmutableSet |
SortedSet/NavigableSet | JDK | ImmutableSortedSet |
Map | JDK | ImmutableMap |
SortedMap | JDK | ImmutableSortedMap |
Multiset | Guava | ImmutableMultiset |
SortedMultiset | Guava | ImmutableSortedMultiset |
Multimap | Guava | ImmutableMultimap |
ListMultimap | Guava | ImmutableListMultimap |
SetMultimap | Guava | ImmutableSetMultimap |
BiMap | Guava | ImmutableBiMap |
ClassToInstanceMap | Guava | ImmutableClassToInstanceMap |
Table | Guava | ImmutableTable |
本文參考:Guava學習筆記:Immutable(不可變)集合 感謝!
想太多,做太少,中間的落差就是煩惱。想沒有煩惱,要么別想,要么多做。中校【12】