標籤:編程實踐 blog 拷貝 的區別 圖片 font 構建 wrap public
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】
【java代碼之美】---guava之Immutable(不可變)集合