<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          強(qiáng)大的集合工具類,java.util.Collections中未包含的集合工具

          共 8544字,需瀏覽 18分鐘

           ·

          2022-03-02 05:46


          任何對JDK集合框架有經(jīng)驗(yàn)的程序員都熟悉和喜歡java.util.Collections包含的工具方法。Guava沿著這些路線提供了更多的工具方法:適用于所有集合的靜態(tài)方法。這是Guava最流行和成熟的部分之一。


          我們用相對直觀的方式把工具類與特定集合接口的對應(yīng)關(guān)系歸納如下:



          ?

          1

          靜態(tài)工廠方法


          在JDK 7之前,構(gòu)造新的范型集合時要討厭地重復(fù)聲明范型:


          List list?= new?ArrayList();


          我想我們都認(rèn)為這很討厭。因此Guava提供了能夠推斷范型的靜態(tài)工廠方法:


          List list?= Lists.newArrayList();
          Map map = Maps.newLinkedHashMap();


          可以肯定的是,JDK7版本的鉆石操作符(<>)沒有這樣的麻煩:


          List list?= new?ArrayList<>();


          但Guava的靜態(tài)工廠方法遠(yuǎn)不止這么簡單。用工廠方法模式,我們可以方便地在初始化時就指定起始元素。


          Set copySet = Sets.newHashSet(elements);
          List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");


          此外,通過為工廠方法命名(Effective Java第一條),我們可以提高集合初始化大小的可讀性:


          List<Type>?exactly100 = Lists.newArrayListWithCapacity(100);
          List<Type>?approx100 = Lists.newArrayListWithExpectedSize(100);
          Set<Type>?approx100Set = Sets.newHashSetWithExpectedSize(100);


          確切的靜態(tài)工廠方法和相應(yīng)的工具類一起羅列在下面的章節(jié)。


          注意:Guava引入的新集合類型沒有暴露原始構(gòu)造器,也沒有在工具類中提供初始化方法。而是直接在集合類中提供了靜態(tài)工廠方法,例如:


          Multiset multiset?= HashMultiset.create();


          Iterables


          在可能的情況下,Guava提供的工具方法更偏向于接受Iterable而不是Collection類型。在Google,對于不存放在主存的集合——比如從數(shù)據(jù)庫或其他數(shù)據(jù)中心收集的結(jié)果集,因?yàn)閷?shí)際上還沒有攫取全部數(shù)據(jù),這類結(jié)果集都不能支持類似size()的操作 ——通常都不會用Collection類型來表示。


          因此,很多你期望的支持所有集合的操作都在Iterables類中。大多數(shù)Iterables方法有一個在Iterators類中的對應(yīng)版本,用來處理Iterator。另外,搜索公眾號終碼一生后臺回復(fù)“資料”,獲取最新面試資料和教程。


          截至Guava 1.2版本,Iterables使用FluentIterable類進(jìn)行了補(bǔ)充,它包裝了一個Iterable實(shí)例,并對許多操作提供了”fluent”(鏈?zhǔn)秸{(diào)用)語法。


          下面列出了一些最常用的工具方法。


          常規(guī)方法



          Iterable concatenated = Iterables.concat(
          ????????Ints.asList(1, 2, 3),
          ????????Ints.asList(4, 5, 6)); // concatenated包括元素 1, 2, 3, 4, 5, 6
          String?lastAdded = Iterables.getLast(myLinkedHashSet);
          String?theElement = Iterables.getOnlyElement(thisSetIsDefinitelyASingleton);
          //如果set不是單元素集,就會出錯了!


          與Collection方法相似的工具方法


          通常來說,Collection的實(shí)現(xiàn)天然支持操作其他Collection,但卻不能操作Iterable。


          下面的方法中,如果傳入的Iterable是一個Collection實(shí)例,則實(shí)際操作將會委托給相應(yīng)的Collection接口方法。例如,往Iterables.size方法傳入是一個Collection實(shí)例,它不會真的遍歷iterator獲取大小,而是直接調(diào)用Collection.size。



          FluentIterable


          除了上面提到的方法,F(xiàn)luentIterable還有一些便利方法用來把自己拷貝到不可變集合




          2

          Lists


          除了靜態(tài)工廠方法和函數(shù)式編程方法,Lists為List類型的對象提供了若干工具方法。



          List?countUp = Ints.asList(1, 2, 3, 4, 5);
          List?countDown = Lists.reverse(theList); // {5, 4, 3, 2, 1}
          List<List> parts = Lists.partition(countUp, 2);//{{1,2}, {3,4}, {5}}


          靜態(tài)工廠方法


          Lists提供如下靜態(tài)工廠方法:



          ?

          3

          Sets


          Sets工具類包含了若干好用的方法。


          集合理論方法


          我們提供了很多標(biāo)準(zhǔn)的集合運(yùn)算(Set-Theoretic)方法,這些方法接受Set參數(shù)并返回SetView,可用于:


          • 直接當(dāng)作Set使用,因?yàn)镾etView也實(shí)現(xiàn)了Set接口;

          • 用copyInto(Set)拷貝進(jìn)另一個可變集合;

          • 用immutableCopy()對自己做不可變拷貝。


          方法

          • union(Set, Set)

          • intersection(Set, Set)

          • difference(Set, Set)

          • symmetricDifference(Set,? ?Set)


          使用范例:


          Set<String> wordsWithPrimeLength = ImmutableSet.of("one", "two", "three", "six", "seven", "eight");
          Set<String> primes = ImmutableSet.of("two", "three", "five", "seven");
          SetView<String> intersection = Sets.intersection(primes,wordsWithPrimeLength);
          // intersection包含"two", "three", "seven"
          return?intersection.immutableCopy();//可以使用交集,但不可變拷貝的讀取效率更高


          其他Set工具方法



          Set animals = ImmutableSet.of("gerbil", "hamster");
          Set fruits = ImmutableSet.of("apple", "orange", "banana");
          Set>>
          product = Sets.cartesianProduct(animals, fruits);
          //?{{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"},
          //??{"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}}
          Set>> animalSets = Sets.powerSet(animals);
          //?{{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}}


          靜態(tài)工廠方法


          Sets提供如下靜態(tài)工廠方法:



          ?

          4

          Maps


          Maps類有若干值得單獨(dú)說明的、很酷的方法。


          uniqueIndex


          Maps.uniqueIndex(Iterable,Function)通常針對的場景是:有一組對象,它們在某個屬性上分別有獨(dú)一無二的值,而我們希望能夠按照這個屬性值查找對象——注:這個方法返回一個Map,鍵為Function返回的屬性值,值為Iterable中相應(yīng)的元素,因此我們可以反復(fù)用這個Map進(jìn)行查找操作。


          比方說,我們有一堆字符串,這些字符串的長度都是獨(dú)一無二的,而我們希望能夠按照特定長度查找字符串:


          ImmutableMapString> stringsByIndex = Maps.uniqueIndex(strings,
          ????new?Function<String, Integer> () {
          ????????public?Integer apply(String?string) {
          ????????????return?string.length();
          ????????}
          ????});


          如果索引值不是獨(dú)一無二的,請參見下面的Multimaps.index方法。另外,搜索公眾號終碼一生后臺回復(fù)“資料”,獲取最新面試資料和教程。


          difference


          Maps.difference(Map, Map)用來比較兩個Map以獲取所有不同點(diǎn)。該方法返回MapDifference對象,把不同點(diǎn)的維恩圖分解為:



          Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
          Map<String, Integer> left = ImmutableMap.of("a", 1, "b", 2, "c", 3);
          MapDifference<String, Integer> diff = Maps.difference(left, right);
          diff.entriesInCommon(); // {"b" => 2}
          diff.entriesInCommon(); // {"b" => 2}
          diff.entriesOnlyOnLeft(); // {"a" => 1}
          diff.entriesOnlyOnRight(); // {"d" => 5}


          處理BiMap的工具方法


          Guava中處理BiMap的工具方法在Maps類中,因?yàn)锽iMap也是一種Map實(shí)現(xiàn)。



          靜態(tài)工廠方法


          Maps提供如下靜態(tài)工廠方法:




          5

          Multisets


          標(biāo)準(zhǔn)的Collection操作會忽略Multiset重復(fù)元素的個數(shù),而只關(guān)心元素是否存在于Multiset中,如containsAll方法。為此,Multisets提供了若干方法,以顧及Multiset元素的重復(fù)性:



          Multiset multiset1 = HashMultiset.create();
          multiset1.add("a", 2);

          Multiset multiset2 = HashMultiset.create();
          multiset2.add("a", 5);
          ?
          multiset1.containsAll(multiset2); //返回true;因?yàn)榘怂胁恢貜?fù)元素,
          //雖然multiset1實(shí)際上包含2個"a",而multiset2包含5個"a"
          Multisets.containsOccurrences(multiset1, multiset2); // returns false
          ?
          multiset2.removeOccurrences(multiset1); // multiset2 現(xiàn)在包含3個"a"

          multiset2.removeAll(multiset1);//multiset2移除所有"a",雖然multiset1只有2個"a"
          multiset2.isEmpty(); // returns true


          Multisets中的其他工具方法還包括:



          Multiset multiset?= HashMultiset.create();
          multiset.add("a", 3);
          multiset.add("b", 5);
          multiset.add("c", 1);
          ?
          ImmutableMultiset highestCountFirst = Multisets.copyHighestCountFirst(multiset);
          //highestCountFirst,包括它的entrySet和elementSet,按{"b", "a", "c"}排列元素



          6

          Multimaps


          Multimaps提供了若干值得單獨(dú)說明的通用工具方法


          index


          作為Maps.uniqueIndex的兄弟方法,Multimaps.index(Iterable, Function)通常針對的場景是:有一組對象,它們有共同的特定屬性,我們希望按照這個屬性的值查詢對象,但屬性值不一定是獨(dú)一無二的。


          比方說,我們想把字符串按長度分組。


          ImmutableSet digits = ImmutableSet.of("zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine");
          Function<String, Integer> lengthFunction = new?Function<String, Integer>() {
          ????public?Integer apply(String?string) {
          ????????return?string.length();
          ????}
          };
          ?
          ImmutableListMultimapString
          > digitsByLength= Multimaps.index(digits, lengthFunction);
          /*
          * digitsByLength maps:
          * 3 => {"one", "two", "six"}
          * 4 => {"zero", "four", "five", "nine"}
          * 5 => {"three", "seven", "eight"}
          */


          invertFrom


          鑒于Multimap可以把多個鍵映射到同一個值(注:實(shí)際上這是任何map都有的特性),也可以把一個鍵映射到多個值,反轉(zhuǎn)Multimap也會很有用。Guava 提供了invertFrom(Multimap toInvert,

          Multimap dest)做這個操作,并且你可以自由選擇反轉(zhuǎn)后的Multimap實(shí)現(xiàn)。


          注:如果你使用的是ImmutableMultimap,考慮改用ImmutableMultimap.inverse()做反轉(zhuǎn)。


          ArrayListMultimap multimap?= ArrayListMultimap.create();
          multimap.putAll("b", Ints.asList(2, 4, 6));
          multimap.putAll("a", Ints.asList(4, 2, 1));
          multimap.putAll("c", Ints.asList(2, 5, 3));
          ?
          TreeMultimap inverse = Multimaps.invertFrom(multimap, TreeMultimap.create());
          //注意我們選擇的實(shí)現(xiàn),因?yàn)檫x了TreeMultimap,得到的反轉(zhuǎn)結(jié)果是有序的
          /*
          * inverse maps:
          * 1 => {"a"}
          * 2 => {"a", "b", "c"}
          * 3 => {"c"}
          * 4 => {"a", "b"}
          * 5 => {"c"}
          * 6 => {"b"}
          */


          forMap


          想在Map對象上使用Multimap的方法嗎?forMap(Map)把Map包裝成SetMultimap。這個方法特別有用,例如,與Multimaps.invertFrom結(jié)合使用,可以把多對一的Map反轉(zhuǎn)為一對多的Multimap。另外,搜索公眾號終碼一生后臺回復(fù)“資料”,獲取最新面試資料和教程。


          Map<String, Integer> map = ImmutableMap.of("a", 1, "b", 1, "c", 2);
          SetMultimap<String, Integer> multimap = Multimaps.forMap(map);
          // multimap:["a" => {1}, "b" => {1}, "c" => {2}]
          MultimapString
          > inverse = Multimaps.invertFrom(multimap, HashMultimapString>.create());
          // inverse:[1 => {"a","b"}, 2 => {"c"}]


          包裝器


          Multimaps提供了傳統(tǒng)的包裝方法,以及讓你選擇Map和Collection類型以自定義Multimap實(shí)現(xiàn)的工具方法。



          自定義Multimap的方法允許你指定Multimap中的特定實(shí)現(xiàn)。但要注意的是:


          • Multimap假設(shè)對Map和Supplier產(chǎn)生的集合對象有完全所有權(quán)。這些自定義對象應(yīng)避免手動更新,并且在提供給Multimap時應(yīng)該是空的,此外還不應(yīng)該使用軟引用、弱引用或虛引用。

          • 無法保證修改了Multimap以后,底層Map的內(nèi)容是什么樣的。

          • 即使Map和Supplier產(chǎn)生的集合都是線程安全的,它們組成的Multimap也不能保證并發(fā)操作的線程安全性。并發(fā)讀操作是工作正常的,但需要保證并發(fā)讀寫的話,請考慮用同步包裝器解決。

          • 只有當(dāng)Map、Supplier、Supplier產(chǎn)生的集合對象、以及Multimap存放的鍵值類型都是可序列化的,Multimap才是可序列化的。

          • Multimap.get(key)返回的集合對象和Supplier返回的集合對象并不是同一類型。但如果Supplier返回的是隨機(jī)訪問集合,那么Multimap.get(key)返回的集合也是可隨機(jī)訪問的。


          請注意,用來自定義Multimap的方法需要一個Supplier參數(shù),以創(chuàng)建嶄新的集合。下面有個實(shí)現(xiàn)ListMultimap的例子——用TreeMap做映射,而每個鍵對應(yīng)的多個值用LinkedList存儲。


          ListMultimap<String, Integer> myMultimap = Multimaps.newListMultimap(
          ????Maps.<String, Collection>newTreeMap(),
          ????new?Supplier() {
          ????????public?LinkedList get() {
          ????????????return?Lists.newLinkedList();
          ????????}
          ????});



          7

          Tables


          Tables類提供了若干稱手的工具方法。


          自定義Table


          堪比Multimaps.newXXXMultimap(Map, Supplier)工具方法,Tables.newCustomTable(Map, Supplier)允許你指定Table用什么樣的map實(shí)現(xiàn)行和列。另外,搜索公眾號終碼一生后臺回復(fù)“資料”,獲取最新面試資料和教程。


          // 使用LinkedHashMaps替代HashMaps
          Table<String, Character, Integer> table = Tables.newCustomTable(
          Maps.<String, Map>newLinkedHashMap(),
          new?Supplier<Map> () {
          public Map get() {
          return?Maps.newLinkedHashMap();
          }
          });


          transpose


          transpose(Table)方法允許你把Table轉(zhuǎn)置成Table。例如,如果你在用Table構(gòu)建加權(quán)有向圖,這個方法就可以把有向圖反轉(zhuǎn)。


          包裝器


          還有很多你熟悉和喜歡的Table包裝類。然而,在大多數(shù)情況下還請使用ImmutableTable



          來源:ifeve.com/google-guava-collectionutilities



          往期推薦



          內(nèi)存耗盡后,Redis會發(fā)生什么?

          Java多線程學(xué)習(xí)之wait、notify/notifyAll 詳解

          為什么要盡量避免使用 IN 和 NOT IN 呢?

          一鍵生成數(shù)據(jù)庫文檔,堪稱數(shù)據(jù)庫界的Swagger

          什么是流式SQL,它有什么用?

          哪些優(yōu)秀的無代碼/低代碼后端開發(fā)利器!你知道幾個?



          瀏覽 40
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  久久久久无码国产精品不卡 | 少妇大战黑人46厘米 | 我要看一级特黄色电影 | www.久久日 | 欧美肏屄网站 |