[Guava] Google Guava 集合工具類

weixin_33782386發表於2018-09-01

Google Guava 集合工具類

Guava中的集合方法擴充套件

任何對JDK集合框架有經驗的程式設計師都熟悉和喜歡java.util.Collections包含的工具方法。Guava沿著這些路線提供了更多的工具方法:適用於所有集合的靜態方法。這是Guava最流行和成熟的部分原因之一。

集合介面 JDK/Guava Guava工具類
Collection JDK Collections2:不要和java.util.Collections混淆
List JDK Lists
Set JDK Sets
SortedSet JDK Sets
Map JDK Maps
SortedMap JDK Maps
Queue JDK Queues
Multiset Guava Multisets
Multimap Guava Multimaps
BiMap Guava Maps
Table Guava Tables

靜態工方法

Person:

/*
 * @ProjectName: 程式設計學習
 * @Copyright:   2018 HangZhou Yiyuery Dev., Ltd. All Right Reserved.
 * @address:     http://xiazhaoyang.tech
 * @date:        2018/8/31 18:15
 * @email:       xiazhaoyang@live.com
 * @description: 本內容僅限於程式設計技術學習使用,轉發請註明出處.
 */
package com.example.chapter1.guava;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.ToString;

/**
 * <p>
 *
 * </p>
 *
 * @author xiachaoyang
 * @version V1.0
 * @date 2018年08月30日 20:37
 * @modificationHistory=========================邏輯或功能性重大變更記錄
 * @modify By: {修改人} 2018年08月30日
 * @modify reason: {方法名}:{原因}
 * ...
 */
@Data
@ToString
@AllArgsConstructor
public class Person {
    private String name;
}

Ex.:

/**
 * 推斷範型的靜態工廠方法
 * - 構造新的範型集合
 * - 初始化起始元素
 * - 工廠法宣告集合變數
 * - 工廠法初始化集合大小
 */
@Test
public void declareStaticFactory(){
    //構造新的範型集合
    List<Person> list = Lists.newArrayList();
    Map<String, Person> map = Maps.newLinkedHashMap();
    Map<String, Person> hsahMap = Maps.newHashMap();
    //...
    list.add(new Person("p1"));
    //初始化起始元素
    Set<Person> copySet = Sets.newHashSet(list);
    System.out.println(copySet);//[Person(name=p1)]
    List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");
    System.out.println(theseElements);//[alpha, beta, gamma]
    //工廠方法命名(Effective Java第一條),我們可以提高集合初始化大小的可讀性
    List<Person> exactly100 = Lists.newArrayListWithCapacity(100);
    List<Person> approx100 = Lists.newArrayListWithExpectedSize(100);
    Set<Person> approx100Set = Sets.newHashSetWithExpectedSize(100);
    //Guava引入的新集合型別沒有暴露原始構造器,也沒有在工具類中提供初始化方法。而是直接在集合類中提供了靜態工廠方法
    Multiset<String> multiset = HashMultiset.create();
}

Iterables

常規方法

集合介面 描述 示例
concat(Iterable<Iterable>) 串聯多個iterables的懶檢視 concat(Iterable...)
frequency(Iterable, Object) 返回物件在iterable中出現的次數 與Collections.frequency (Collection,Object)比較;Multiset
partition(Iterable, int) 把iterable按指定大小分割,得到的子集都不能進行修改操作 Lists.partition(List, int);paddedPartition(Iterable, int)
getFirst(Iterable, T default) 返回iterable的第一個元素,若iterable為空則返回預設值 與Iterable.iterator().next()比較;FluentIterable.first()
getLast(Iterable) 返回iterable的最後一個元素,若iterable為空則丟擲NoSuchElementException getLast(Iterable, T default);FluentIterable.last()
elementsEqual(Iterable, Iterable) 如果兩個iterable中的所有元素相等且順序一致,返回true 與List.equals(Object)比較
unmodifiableIterable(Iterable) 返回iterable的不可變檢視 與Collections.unmodifiableCollection(Collection)比較
limit(Iterable, int) 限制iterable的元素個數限制給定值 FluentIterable.limit(int)
getOnlyElement(Iterable) 獲取iterable中唯一的元素,如果iterable為空或有多個元素,則快速失敗 getOnlyElement(Iterable, T default)

>注:懶檢視意味著如果還沒訪問到某個iterable中的元素,則不會對它進行串聯操作

/**
 * 在可能的情況下,Guava提供的工具方法更偏向於接受Iterable而不是Collection型別。
 * 在Google,對於不存放在主存的集合(比如從資料庫或其他資料中心收集的結果集)
 * 因為實際上還沒有獲取全部資料,這類結果集都不能支援類似size()的操作,通常都不會用Collection型別來表示。
 */
@Test
public void  testGuavaIterables(){
    Set<Integer> linkedHashSet = Sets.newLinkedHashSet();
    linkedHashSet.add(7);
    Iterable<Integer> iterable = Iterables.concat(Ints.asList(1,2,3),Ints.asList(4,5,6),linkedHashSet);
    Integer last = Iterables.getLast(linkedHashSet);
    System.out.println(iterable);
    System.out.println(last);
    //[1, 2, 3, 4, 5, 6, 7]
    //7
    Integer element = Iterables.getOnlyElement(linkedHashSet);
    System.out.println(element);
    //7
    linkedHashSet.add(8);
    element = Iterables.getOnlyElement(linkedHashSet);
    System.out.println(element);
    //java.lang.IllegalArgumentException: expected one element but was: <7, 8> linkedHashSet 如果不是單元素就會報錯!
}

與Collection方法相似的工具方法

Iterables

方法 類似的Collection方法 等價的FluentIterable方法
addAll(Collection addTo, Iterable toAdd) Collection.addAll(Collection)
contains(Iterable, Object) Collection.contains(Object) FluentIterable.contains(Object)
removeAll(Iterable removeFrom, Collection toRemove) Collection.removeAll(Collection)
retainAll(Iterable removeFrom, Collection toRetain) Collection.retainAll(Collection)
size(Iterable) Collection.size() FluentIterable.size()
toArray(Iterable, Class) Collection.toArray(T[]) FluentIterable.toArray(Class)
isEmpty(Iterable) Collection.isEmpty() FluentIterable.isEmpty()
get(Iterable, int) List.get(int) FluentIterable.get(int)
toString(Iterable) Collection.toString() FluentIterable.toString()

>注:上面的方法中,如果傳入的Iterable是一個Collection例項,則實際操作將會委託給相應的Collection介面方法。例如,往Iterables.size方法傳入是一個Collection例項,它不會真的遍歷iterator獲取大小,而是直接呼叫Collection.size。

    //通常來說 Collection的實現天然支援操作其他Collection,但卻不能操作Iterable。
    List<Person> list = Lists.newArrayList();
    list.add(new Person("p1"));
    System.out.println(Iterables.size(list));//1

原始碼:

/** Returns the number of elements in {@code iterable}. */
public static int size(Iterable<?> iterable) {
  return (iterable instanceof Collection)
      ? ((Collection<?>) iterable).size()
      : Iterators.size(iterable.iterator());
}

FluentIterable 還有一些便利方法用來把自己拷貝到 不可變集合

名稱 方法
ImmutableSet toSet()
ImmutableSortedSet toImmutableSortedSet(Comparator)
/**
 * FluentIterable還有一些便利方法用來把自己拷貝到不可變集合
 * 為什麼要用immutable物件?immutable物件有以下的優點:
 *  1.對不可靠的客戶程式碼庫來說,它使用安全,可以在未受信任的類庫中安全的使用這些物件
 *  2.執行緒安全的:immutable物件在多執行緒下安全,沒有競態條件
 *  3.不需要支援可變性, 可以儘量節省空間和時間的開銷. 所有的不可變集合實現都比可變集合更加有效的利用記憶體 (analysis)
 *  4.可以被使用為一個常量,並且期望在未來也是保持不變的
 * Guava提供了對JDK裡標準集合類裡的immutable版本的簡單方便的實現,以及Guava自己的一些專門集合類的immutable實現。當你不希望修改一個集合類,或者想做一個常量集合類的時候,使用immutable集合類就是一個最佳的程式設計實踐
 * 注意:每個Guava immutable集合類的實現都拒絕null值。我們做過對Google內部程式碼的全面的調查,並且發現只有5%的情況下集合類允許null值,而95%的情況下都拒絕null值。萬一你真的需要能接受null值的集合類,你可以考慮用Collections.unmodifiableXXX。
 * Immutable集合使用方法,一個immutable集合可以有以下幾種方式來建立:
 *   1.用copyOf方法, 譬如, ImmutableSet.copyOf(set)
 *   2.使用of方法,譬如,ImmutableSet.of("a", "b", "c")或者ImmutableMap.of("a", 1, "b", 2)
 *   3.使用Builder類
 *
 */
@Test
public void testGuavaFluentIterable(){
   Set<Integer> linkedHashSet = Sets.newLinkedHashSet();
   linkedHashSet.add(7);
   ImmutableSet<Integer> immutableSet = ImmutableSet.copyOf(linkedHashSet);
   System.out.println(immutableSet);//[7]
   immutableSet = ImmutableSet.of(4,5,6);
   System.out.println(immutableSet);//[4, 5, 6]
   ImmutableMap<String, Integer> immutableMap = ImmutableMap.of("a", 1, "b", 2);
   System.out.println(immutableMap);//{a=1, b=2}
   ImmutableSet<Person> personImmutableSet =
           ImmutableSet.<Person>builder()
                   .add(new Person("p1"))
                   .add(new Person("p2"))
                   .build();
   System.out.println(personImmutableSet);//[Person(name=p1), Person(name=p2)]
   //拷貝到不可變集合
   immutableSet = FluentIterable.of(7,8,9).toSet();
   System.out.println(immutableSet);//[7, 8, 9]
   //拷貝到不可變集合(排序)
   Comparator<Integer> comparator = (h1, h2) -> h1.compareTo(h2);
   immutableSet = FluentIterable.of(7, 8, 9, 5, 4, 7, 9).toSortedSet(comparator);
   System.out.println(immutableSet);//[4, 5, 7, 8, 9]
   //反轉排序
   immutableSet = FluentIterable.of(7, 8, 9, 5, 4, 7, 9).toSortedSet(comparator.reversed());
   System.out.println(immutableSet);//[9, 8, 7, 5, 4]
}

Lists

靜態工廠方法

名稱 方法(根據入參型別不同區分)
ArrayList basic, with elements, from Iterable, from Iterator, with exact capacity, with expected size
LinkedList basic, from Iterable

>注:

  • basic : 無參構造器
  • with elements : E... elements
  • from Iterable : Iterable<? extends E> elements
  • from Iterator : Iterator<? extends E> elements
  • with exact capacity : int initialArraySize
  • with expected size : int estimatedSize

除了靜態工廠方法和函數語言程式設計方法,Lists為List型別的物件提供了若干工具方法。

方法 描述
partition(List, int) 把List按指定大小分割
reverse(List) 返回給定List的反轉檢視。注: 如果List是不可變的,考慮改用ImmutableList.reverse()
/**
  * Lists 方法測試
  */
  @Test
  public void testLists(){
     //反轉排序
     List list = Ints.asList(1, 2, 3, 4, 5);
     System.out.println(Lists.reverse(list));//[5, 4, 3, 2, 1]
     //指定大小分割
     List<List> parts = Lists.partition(list, 2);
     System.out.println(parts);//[[1, 2], [3, 4], [5]]
     List<Integer> iList = Lists.newArrayList();
     List<Integer> iList2 = Lists.newArrayList(1, 2, 3);
     List<Integer> iList3 = Lists.newArrayList(iList2.iterator());
     List<Integer> iList4 = Lists.newArrayList(Iterables.concat(iList2));
     List<Integer> iList5 = Lists.newArrayListWithCapacity(1);
     List<Integer> iList6 = Lists.newArrayListWithExpectedSize(1);
     System.out.println(iList);//[]
     System.out.println(iList2);//[1, 2, 3]
     System.out.println(iList3);//[1, 2, 3]
     System.out.println(iList4);//[1, 2, 3]
     System.out.println(iList5);//[]
     System.out.println(iList6);//[]
     iList5.addAll(iList2);
     System.out.println(iList5);//[1, 2, 3]
     iList6.addAll(iList2);
     System.out.println(iList6);//[1, 2, 3]
}

REFRENCES

  1. [Google Guava] 2.3-強大的集合工具類:java.util.Collections中未包含的集合工具
  2. Guava學習筆記:Immutable(不可變)集合
  3. guava翻譯系列之Collections
  4. Java8:Lambda表示式增強版Comparator和排序
  5. guava之Lists常用示例及newArrayListWithExpectedSize()和newArrayListWithCapacity()詳細對比

微信公眾號

3734705-dcbe630eb27be3f9.png
image

掃碼關注或搜尋架構探險之道獲取最新文章,不積跬步無以至千里,堅持每週一更,堅持技術分享。我和你們一起成長 _

相關文章