Guava庫介紹之集合(Collection)相關的API


作者:Jack47

轉載請保留作者和原文出處

歡迎關注我的微信公眾賬號程序員傑克,兩邊的文章會同步,也可以添加我的RSS訂閱源

本文是我寫的Google開源的Java編程庫Guava系列之一,主要介紹Guava中提供的集合(Collection)相關的API。

1. 一些小功能##

集合聲明更簡單###

Java中同質的范型集合是一個很大的特色,但是有些時候他們的構造函數有點太啰嗦了,比如:

Map<String, Map<String, Integer>> lookup = new HashMap<String, Map<String, Integer>>();

在Java 7中通過鑽石操作符<>來允許有限的非正式的類型推導。上面的例子可以這樣寫:

Map<String, Map<String, Integer>> lookup = new HashMap<>();

Guava提供了一些使用范型來進行右側類型推導的靜態函數,使得集合的聲明更簡單,上面的例子可以這么寫:

Map<String, Map<String, String>> map = Maps.newHashMap();
List<List<Map<String, String>>> list = Lists.newArrayList();

集合初始化更簡單###

可以在集合聲明時進行初始化

Set<String> set = Sets.newHashSet("one", "two", "three");
Map<String, String> map = ImmutableMap.of("ON", true, "OFF", false);

2. 不可變性(Immutability)##

大部分google提供的集合都提供不可變的版本。
當你不會修改一個集合,或者期望一個集合是固定不變的,那么一個很好的習慣是防御式地把它拷貝成一個不可變的集合。

注意

Guava中提供的不可變集合的實現是不允許有空值`null`的。因為通過研究Google內部代碼庫發現在集合中,只有5%的情況下是允許有空值的,剩下的95%情況下最好是遇到空值就快速失敗(failing fast)。如果需要空值,可以使用JDK中提供的 Collections.unmodifiableList 這類允許空值的集合實現。

更多關於使用或者避免使用null的細節見Using And Avoiding Null Explained

不可變的好處

  • 可以放心的給不信任的庫使用
  • 線程安全:可以被多個線程使用而不會有競爭條件發生
  • 不需要同步(synchronization)的邏輯,不需要支持互斥
  • 設計和實現很簡單。所有不可變的集合實現比可變版本的內存效率要高,分析見這里

如何使用###

有多種方法來得到一個不可變的集合:

  1. 使用of函數

    ImmutableSet<Integer> numbers = ImmutableSet.of(10, 30, 40, 50);

  2. 使用copyOf函數

    ImmutableSet<Integer> another = ImmutableSet.copyOf(numberSet);

所有不可變的集合都通過asList()提供了一個不可變的List(ImmutableList)視圖。例如數據存儲在一個ImmutableSortedSet里,可以通過sortedSet.asList().get(k)來獲得第k個最小的元素。

JDK雖然提供了Collections.unmodifiableXXX方法,但是有一些問題:

  • 非常笨重,使用起來很啰嗦,用着不爽
  • 不安全:只有當沒有對原始集合的引用時,這個函數返回的集合才是真的不可變的
  • 不夠高效:數據結構里還是有可變集合里關於並發修改的檢查,存儲哈希表的額外空間等。

3. 新的集合類型##

Guava引入的新的集合類型並沒有暴露原始的構造函數,或者提供方便初始化操作的工具類,而是直接使用靜態工廠函數,例如:

MultiMap<String, Integer> multiMap = HashMultiMap.create();

MultiMap###

容許一個key有多個值的MultiMap, MultiMap<K, V>可以取代傳統的Map<K, Collection<V>>。也可以使用值為鏈表的ListMultiMap或者集合SetMultiMap

Multiset###

Multiset支持添加多次相同的值,支持對值進行計數。

Multiset<Integer> multiSet = HashMultiset.create();
multiSet.add(10);
multiSet.add(30);
multiSet.add(30);
multiSet.add(40);
multiSet.count(30); // 2
multiSet.size(); // 4

Table###

表結構的數據類型Table,它像Map一樣,但是支持兩種鍵--行鍵(row key)和列鍵(column key)。

4. 謂語(Predicate)和過濾器(Filter)##

謂語(Predicate)是一個只包含一個返回布爾類型的函數的簡單接口。它的作用是給定一個輸入,判斷是否滿足條件。它可以用來過濾集合,例如實現一個過濾出老客戶的Predicate

static class LoyalCustomer implements Predicate<Customer> {
	public boolean apply(Customer customer) {
		return CustomerType.LOYAL == customer.getCustomerType();
	}
}
Collection<Customer> loyalCustomers =  	Collections2.filter(customers, new LoyalCustomer());

filter函數的語法是:
Collection<E> filter(Collection<E> unfiltered, Predicate<E> predicate)

內置的Predicate####

Predicates類包含了andornot in這幾個靜態函數來方便構建復雜的謂語。

Predicate<String> commonList = and(in(list1), in(list2, or(in(list3));

Predicates類也包含了很多非常方便的函數,例如notNull, instanceOf, contains等。

SortedMaps.filterValues(map, Predicates.notNull());

如果看到這里還意猶未盡的話,建議去看看源代碼單測的代碼,里面有詳盡的用法!

參考資料:

Immutable Collections

Collection Utilities


如果您看了本篇博客,覺得對您有所收獲,請點擊右下角的“推薦”,讓更多人看到!
資助Jack47寫作,打賞一個雞蛋灌餅錢吧
pay_weixin
微信打賞
pay_alipay
支付寶打賞


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM