日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

Immutable(不可变)集合

發(fā)布時(shí)間:2023/12/31 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 Immutable(不可变)集合 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Immutable(不可變)集合

不可變集合,顧名思義就是說集合是不可被修改的。集合的數(shù)據(jù)項(xiàng)是在創(chuàng)建的時(shí)候提供,并且在整個(gè)生命周期中都不可改變。

  為什么要用immutable對象?immutable對象有以下的優(yōu)點(diǎn):
    1.對不可靠的客戶代碼庫來說,它使用安全,可以在未受信任的類庫中安全的使用這些對象
    2.線程安全的:immutable對象在多線程下安全,沒有競態(tài)條件
    3.不需要支持可變性, 可以盡量節(jié)省空間和時(shí)間的開銷. 所有的不可變集合實(shí)現(xiàn)都比可變集合更加有效的利用內(nèi)存 (analysis)
    4.可以被使用為一個(gè)常量,并且期望在未來也是保持不變的

  immutable對象可以很自然地用作常量,因?yàn)樗鼈兲焐褪遣豢勺兊膶τ趇mmutable對象的運(yùn)用來說,它是一個(gè)很好的防御編程(defensive programming)的技術(shù)實(shí)踐。

  JDK中實(shí)現(xiàn)immutable集合

  在JDK中提供了Collections.unmodifiableXXX系列方法來實(shí)現(xiàn)不可變集合, 但是存在一些問題,下面我們先看一個(gè)具體實(shí)例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.junit.Test;

public class ImmutableTest {
    @Test
    public void testJDKImmutable(){                                                                                                                                                                                                                                    
        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 unmodifiableList1:[a, b, c, baby]

  說明:Collections.unmodifiableList實(shí)現(xiàn)的不是真正的不可變集合,當(dāng)原始集合修改后,不可變集合也發(fā)生變化。不可變集合不可以修改集合數(shù)據(jù),當(dāng)強(qiáng)制修改時(shí)會(huì)報(bào)錯(cuò),實(shí)例中的最后兩個(gè)add會(huì)直接拋出不可修改的錯(cuò)誤。

  總結(jié)一下JDK的Collections.unmodifiableXXX方法實(shí)現(xiàn)不可變集合的一些問題:

  1.它用起來笨拙繁瑣你不得不在每個(gè)防御性編程拷貝的地方用這個(gè)方法
  2.它不安全:如果有對象reference原始的被封裝的集合類,這些方法返回的集合也就不是正真的不可改變。
  3.效率低:因?yàn)樗祷氐臄?shù)據(jù)結(jié)構(gòu)本質(zhì)仍舊是原來的集合類,所以它的操作開銷,包括并發(fā)下修改檢查,hash table里的額外數(shù)據(jù)空間都和原來的集合是一樣的。

  Guava的immutable集合

  Guava提供了對JDK里標(biāo)準(zhǔn)集合類里的immutable版本的簡單方便的實(shí)現(xiàn),以及Guava自己的一些專門集合類的immutable實(shí)現(xiàn)。當(dāng)你不希望修改一個(gè)集合類,或者想做一個(gè)常量集合類的時(shí)候,使用immutable集合類就是一個(gè)最佳的編程實(shí)踐。

注意:每個(gè)Guava immutable集合類的實(shí)現(xiàn)都拒絕null值。我們做過對Google內(nèi)部代碼的全面的調(diào)查,并且發(fā)現(xiàn)只有5%的情況下集合類允許null值,而95%的情況下都拒絕null值。萬一你真的需要能接受null值的集合類,你可以考慮用Collections.unmodifiableXXX。

  Immutable集合使用方法:
  一個(gè)immutable集合可以有以下幾種方式來創(chuàng)建:
  1.用copyOf方法, 譬如, ImmutableSet.copyOf(set)
  2.使用of方法,譬如,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)
  3.使用Builder類

  實(shí)例:

@Test
    public void testGuavaImmutable(){
        
        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);
        
        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]]

  對于排序的集合來說有例外,因?yàn)樵氐捻樞蛟跇?gòu)建集合的時(shí)候就被固定下來了。譬如,ImmutableSet.of("a", "b", "c", "a", "d", "b"),對于這個(gè)集合的遍歷順序來說就是"a", "b", "c", "d"。

  更智能的copyOf

  copyOf方法比你想象的要智能,ImmutableXXX.copyOf會(huì)在合適的情況下避免拷貝元素的操作-先忽略具體的細(xì)節(jié),但是它的實(shí)現(xiàn)一般都是很“智能”的。譬如:

@Test
    public void testCotyOf(){
        ImmutableSet<String> imSet=ImmutableSet.of("peida","jerry","harry","lisa");
        System.out.println("imSet:"+imSet);
        ImmutableList<String> imlist=ImmutableList.copyOf(imSet);
        System.out.println("imlist:"+imlist);
        ImmutableSortedSet<String> imSortSet=ImmutableSortedSet.copyOf(imSet);
        System.out.println("imSortSet:"+imSortSet);
        
        List<String> list=new ArrayList<String>();
        for(int i=0;i<20;i++){
            list.add(i+"x");
        }
        System.out.println("list:"+list);
        ImmutableList<String> imInfolist=ImmutableList.copyOf(list.subList(2, 18));
        System.out.println("imInfolist:"+imInfolist);
        int imInfolistSize=imInfolist.size();
        System.out.println("imInfolistSize:"+imInfolistSize);
        ImmutableSet<String> imInfoSet=ImmutableSet.copyOf(imInfolist.subList(2, imInfolistSize-3));
        System.out.println("imInfoSet:"+imInfoSet);
    }

  輸出: 

imSet:[peida, jerry, harry, lisa]
imlist:[peida, jerry, harry, lisa]
imSortSet:[harry, jerry, lisa, peida]
list:[0x, 1x, 2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x, 15x, 16x, 17x, 18x, 19x]
imInfolist:[2x, 3x, 4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x, 15x, 16x, 17x]
imInfolistSize:16
imInfoSet:[4x, 5x, 6x, 7x, 8x, 9x, 10x, 11x, 12x, 13x, 14x]

  在這段代碼中,ImmutableList.copyOf(imSet)會(huì)智能地返回時(shí)間復(fù)雜度為常數(shù)的ImmutableSet的imSet.asList()。
  一般來說,ImmutableXXX.copyOf(ImmutableCollection)會(huì)避免線性復(fù)雜度的拷貝操作。如在以下情況:
  這個(gè)操作有可能就利用了被封裝數(shù)據(jù)結(jié)構(gòu)的常數(shù)復(fù)雜度的操作。但例如ImmutableSet.copyOf(list)不能在常數(shù)復(fù)雜度下實(shí)現(xiàn)。
  這樣不會(huì)導(dǎo)致內(nèi)存泄漏-例如,你有個(gè)ImmutableList<String> imInfolist,然后你顯式操作ImmutableList.copyOf(imInfolist.subList(0, 10))。這樣的操作可以避免意外持有不再需要的在hugeList里元素的reference。
  它不會(huì)改變集合的語意-像ImmutableSet.copyOf(myImmutableSortedSet)這樣的顯式拷貝操作,因?yàn)樵贗mmutableSet里的hashCode()和equals()的含義和基于comparator的ImmutableSortedSet是不同的。
  這些特性有助于最優(yōu)化防御性編程的性能開銷。

  asList方法

  所有的immutable集合都以asList()的形式提供了ImmutableList視圖(view)。譬如,你把數(shù)據(jù)放在ImmutableSortedSet,你就可以調(diào)用sortedSet.asList().get(k)來取得前k個(gè)元素的集合。
  返回的ImmutableList常常是個(gè)常數(shù)復(fù)雜度的視圖,而不是一個(gè)真的拷貝。也就是說,這個(gè)返回集合比一般的List更智能-譬如,它會(huì)更高效地實(shí)現(xiàn)contains這樣的方法。

  實(shí)例:

@Test
    public void testAsList(){
        ImmutableList<String> imList=ImmutableList.of("peida","jerry","harry","lisa","jerry");
        System.out.println("imList:"+imList);
        ImmutableSortedSet<String> imSortList=ImmutableSortedSet.copyOf(imList);
        System.out.println("imSortList:"+imSortList);
        System.out.println("imSortList as list:"+imSortList.asList());
    }

  輸出:

imList:[peida, jerry, harry, lisa, jerry]
imSortList:[harry, jerry, lisa, peida]
imSortList as list:[harry, jerry, lisa, peida]

  Guava集合和不可變對應(yīng)關(guān)系

可變集合類型 可變集合源: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

總結(jié)

以上是生活随笔為你收集整理的Immutable(不可变)集合的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。