# 2.3-強大的集合工具類:java.util.Collections中未包含的集合工具
# 2.3-強大的集合工具類:java.util.Collections中未包含的集合工具
[原文鏈接](http://code.google.com/p/guava-libraries/wiki/CollectionUtilitiesExplained) [譯文鏈接](http://ifeve.com/google-guava-collectionutilities) 譯者:沈義揚,校對:丁一
*尚未完成: Queues, Tables工具類*
任何對JDK集合框架有經驗的程序員都熟悉和喜歡[`java.util.Collections`](http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html)包含的工具方法。Guava沿著這些路線提供了更多的工具方法:適用于所有集合的靜態方法。這是Guava最流行和成熟的部分之一。
我們用相對直觀的方式把工具類與特定集合接口的對應關系歸納如下:
**集合接口****屬于\*\***JDK****還是****Guava\*\***對應的\*\***Guava**\*\*工具類**CollectionJDK[`Collections2`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Collections2.html):不要和java.util.Collections混淆ListJDK[`Lists`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Lists.html)SetJDK[`Sets`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Sets.html)SortedSetJDK[`Sets`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Sets.html)MapJDK[`Maps`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Maps.html)SortedMapJDK[`Maps`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Maps.html)QueueJDK[`Queues`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Queues.html)[Multiset](http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset)Guava[`Multisets`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multisets.html)[Multimap](http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multimap)Guava[`Multimaps`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html)[BiMap](http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#BiMap)Guava[`Maps`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html)[Table](http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Table)Guava[`Tables`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Tables.html)*在找類似轉化、過濾的方法?請看第四章,函數式風格。*
## 靜態工廠方法
在JDK 7之前,構造新的范型集合時要討厭地重復聲明范型:
```
<pre class="calibre11">```
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();
```
```
我想我們都認為這很討厭。因此Guava提供了能夠推斷范型的靜態工廠方法:
```
<pre class="calibre11">```
List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();
```
```
可以肯定的是,JDK7版本的鉆石操作符(<>)沒有這樣的麻煩:
```
<pre class="calibre11">```
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();
```
```
但Guava的靜態工廠方法遠不止這么簡單。用工廠方法模式,我們可以方便地在初始化時就指定起始元素。
```
<pre class="calibre11">```
Set<Type> copySet = Sets.newHashSet(elements);
List<String> theseElements = Lists.newArrayList("alpha", "beta", "gamma");
```
```
此外,通過為工廠方法命名(Effective Java第一條),我們可以提高集合初始化大小的可讀性:
```
<pre class="calibre11">```
List<Type> exactly100 = Lists.newArrayListWithCapacity(100);
List<Type> approx100 = Lists.newArrayListWithExpectedSize(100);
Set<Type> approx100Set = Sets.newHashSetWithExpectedSize(100);
```
```
確切的靜態工廠方法和相應的工具類一起羅列在下面的章節。
注意:Guava引入的新集合類型沒有暴露原始構造器,也沒有在工具類中提供初始化方法。而是直接在集合類中提供了靜態工廠方法,例如:
```
<pre class="calibre11">```
Multiset<String> multiset = HashMultiset.create();
```
```
## Iterables
在可能的情況下,Guava提供的工具方法更偏向于接受Iterable而不是Collection類型。在Google,對于不存放在主存的集合——比如從數據庫或其他數據中心收集的結果集,因為實際上還沒有攫取全部數據,這類結果集都不能支持類似size()的操作 ——通常都不會用Collection類型來表示。
因此,很多你期望的支持所有集合的操作都在[`Iterables`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html)類中。大多數Iterables方法有一個在[Iterators](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterators.html)類中的對應版本,用來處理Iterator。
截至Guava 1.2版本,Iterables使用`[FluentIterable](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html)類`進行了補充,它包裝了一個Iterable實例,并對許多操作提供了”fluent”(鏈式調用)語法。
下面列出了一些最常用的工具方法,但更多Iterables的函數式方法將在第四章討論。
### 常規方法
[`concat(Iterable<Iterable>)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#concat%28java.lang.Iterable%29)串聯多個iterables的懶視圖\*[`concat(Iterable...)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#concat%28java.lang.Iterable...%29)[`frequency(Iterable, Object)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#frequency%28java.lang.Iterable,%20java.lang.Object%29)返回對象在iterable中出現的次數與Collections.frequency (Collection, Object)比較;[Multiset](http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained#Multiset)[`partition(Iterable, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#partition%28java.lang.Iterable,%20int%29)把iterable按指定大小分割,得到的子集都不能進行修改操作[`Lists.partition(List, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#partition%28java.util.List,%20int%29);[`paddedPartition(Iterable, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#paddedPartition%28java.lang.Iterable,%20int%29)[`getFirst(Iterable, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#getFirst%28java.lang.Iterable,%20T%29)返回iterable的第一個元素,若iterable為空則返回默認值與Iterable.iterator(). next()比較;[`FluentIterable.first()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#first%28%29)[`getLast(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#getLast%28java.lang.Iterable%29)返回iterable的最后一個元素,若iterable為空則拋出NoSuchElementException[`getLast(Iterable, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#getLast%28java.lang.Iterable,%20T%29);[`FluentIterable.last()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#last%28%29) | | [`elementsEqual(Iterable, Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#elementsEqual%28java.lang.Iterable,%20java.lang.Iterable%29) | 如果兩個iterable中的所有元素相等且順序一致,返回true | 與List.equals(Object)比較 | | [`unmodifiableIterable(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ogle/common/collect/Iterables.html#unmodifiableIterable%28java.lang.Iterable%29) | 返回iterable的不可變視圖 | 與Collections. unmodifiableCollection(Collection)比較 | | [`limit(Iterable, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#limit%28java.lang.Iterable,%20int%29) | 限制iterable的元素個數限制給定值 | [`FluentIterable.limit(int)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#limit%28int%29) | | [`getOnlyElement(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#getOnlyElement%28java.lang.Iterable%29) | 獲取iterable中唯一的元素,如果iterable為空或有多個元素,則快速失敗 | [`getOnlyElement(Iterable, T default)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#getOnlyElement%28java.lang.Iterable,%20T%29) |
*\*譯者注:懶視圖意味著如果還沒訪問到某個iterable中的元素,則不會對它進行串聯操作。*
```
<pre class="calibre11">```
Iterable<Integer> 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的實現天然支持操作其他Collection,但卻不能操作Iterable。
下面的方法中,如果傳入的Iterable是一個Collection實例,則實際操作將會委托給相應的Collection接口方法。例如,往Iterables.size方法傳入是一個Collection實例,它不會真的遍歷iterator獲取大小,而是直接調用Collection.size。
**方法****類似的\*\***Collection**\*\*方法****等價的\*\***FluentIterable**\*\*方法**[`addAll(Collection addTo, Iterable toAdd)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#addAll%28java.util.Collection,%20java.lang.Iterable%29)Collection.addAll(Collection)[`contains(Iterable, Object)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#contains%28java.lang.Iterable,%20java.lang.Object%29)Collection.contains(Object)[`FluentIterable.contains(Object)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#contains%28java.lang.Object%29)[`removeAll(Iterable removeFrom, Collection toRemove)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#removeAll%28java.lang.Iterable,%20java.util.Collection%29)Collection.removeAll(Collection)[`retainAll(Iterable removeFrom, Collection toRetain)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#retainAll%28java.lang.Iterable,%20java.util.Collection%29)Collection.retainAll(Collection)[`size(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#size%28java.lang.Iterable%29)Collection.size()[`FluentIterable.size()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#size%28%29)[`toArray(Iterable, Class)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#toArray%28java.lang.Iterable,%20java.lang.Class%29)Collection.toArray(T\[\])[`FluentIterable.toArray(Class)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#toArray%28java.lang.Class%29)[`isEmpty(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#isEmpty%28java.lang.Iterable%29)Collection.isEmpty()[`FluentIterable.isEmpty()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#isEmpty%28%29)[`get(Iterable, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#get%28java.lang.Iterable,%20int%29)List.get(int)[`FluentIterable.get(int)`](http://docs.guava-libraries.googlecode.com/git-%20history/release12/javadoc/com/google/common/collect/FluentIterable.html#get%28int%29)[`toString(Iterable)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Iterables.html#toString%28java.lang.Iterable%29)Collection.toString()[`FluentIterable.toString()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#toString%28%29)### FluentIterable
除了上面和第四章提到的方法,FluentIterable還有一些便利方法用來把自己拷貝到不可變集合
ImmutableListImmutableSet[`toImmutableSet()`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/com/google/common/collect/FluentIterable.html#toImmutableSet%28%29)ImmutableSortedSet[`toImmutableSortedSet(Comparator)`](http://docs.guava-libraries.googlecode.com/git-history/release12/javadoc/co%E2%80%A6mmon/collect/FluentIterable.html#toImmutableSortedSet%28java.util.Comparator%29)## Lists
除了靜態工廠方法和函數式編程方法,[`Lists`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Lists.html)為List類型的對象提供了若干工具方法。
**方法****描述**[`partition(List, int)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#partition%28java.util.List,%20int%29)把List按指定大小分割[`reverse(List)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#reverse%28java.util.List%29)返回給定List的反轉視圖。注: 如果List是不可變的,考慮改用[`ImmutableList.reverse()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableList.html#reverse%28%29)。```
<pre class="calibre11">```
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}}
```
```
### 靜態工廠方法
Lists提供如下靜態工廠方法:
**具體實現類型****工廠方法**ArrayList[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayList%28%29), [with elements](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayList%28E...%29), [from `Iterable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayList%28java.lang.Iterable%29), [with exact capacity](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayListWithCapacity%28int%29), [with expected size](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayListWithExpectedSize%28int%29), [from `Iterator`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newArrayList%28java.util.Iterator%29)LinkedList[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newLinkedList%28%29), [from `Iterable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Lists.html#newLinkedList%28java.lang.Iterable%29)## Sets
[`Sets`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Sets.html)工具類包含了若干好用的方法。
### 集合理論方法
我們提供了很多標準的集合運算(Set-Theoretic)方法,這些方法接受Set參數并返回[`SetView`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.SetView.html),可用于:
- 直接當作Set使用,因為SetView也實現了Set接口;
- 用[`copyInto(Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.SetView.html#copyInto%28S%29)拷貝進另一個可變集合;
- 用[`immutableCopy()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.SetView.html#immutableCopy%28%29)對自己做不可變拷貝。
**方法**[`union(Set, Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#union%28java.util.Set,%20java.util.Set%29)[`intersection(Set, Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#intersection%28java.util.Set,%20java.util.Set%29)[`difference(Set, Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#difference%28java.util.Set,%20java.util.Set%29)[`symmetricDifference(Set, Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#symmetricDifference%28java.util.Set,%20java.util.Set%29)使用范例:
```
<pre class="calibre11">```
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工具方法
**方法****描述****另請參見**[`cartesianProduct(List<Set>)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#cartesianProduct%28java.util.List%29)返回所有集合的笛卡兒積[`cartesianProduct(Set...)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#cartesianProduct%28java.util.Set...%29)[`powerSet(Set)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#powerSet%28java.util.Set%29)返回給定集合的所有子集```
<pre class="calibre11">```
Set<String> animals = ImmutableSet.of("gerbil", "hamster");
Set<String> fruits = ImmutableSet.of("apple", "orange", "banana");
Set<List<String>> product = Sets.cartesianProduct(animals, fruits);
// {{"gerbil", "apple"}, {"gerbil", "orange"}, {"gerbil", "banana"},
// {"hamster", "apple"}, {"hamster", "orange"}, {"hamster", "banana"}}
Set<Set<String>> animalSets = Sets.powerSet(animals);
// {{}, {"gerbil"}, {"hamster"}, {"gerbil", "hamster"}}
```
```
### 靜態工廠方法
Sets提供如下靜態工廠方法:
**具體實現類型****工廠方法**HashSet[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newHashSet%28%29), [with elements](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newHashSet%28E...%29), [from `Iterable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newHashSet%28java.lang.Iterable%29), [with expected size](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newHashSetWithExpectedSize%28int%29), [from `Iterator`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newHashSet%28java.util.Iterator%29)LinkedHashSet[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newLinkedHashSet%28%29), [from `Iterable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newLinkedHashSet%28java.lang.Iterable%29), [with expected size](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newLinkedHashSetWithExpectedSize%28int%29)TreeSet[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newTreeSet%28%29), [with `Comparator`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newTreeSet%28java.util.Comparator%29), [from `Iterable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Sets.html#newTreeSet%28java.lang.Iterable%29)## Maps
[`Maps`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html)類有若干值得單獨說明的、很酷的方法。
### uniqueIndex
[`Maps.uniqueIndex(Iterable,Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#uniqueIndex%28java.lang.Iterable,%20com.google.common.base.Function%29)通常針對的場景是:有一組對象,它們在某個屬性上分別有獨一無二的值,而我們希望能夠按照這個屬性值查找對象——*譯者注:這個方法返回一個\_\_Map,鍵為Function返回的屬性值,值為Iterable中相應的元素,因此我們可以反復用這個Map進行查找操作。*
比方說,我們有一堆字符串,這些字符串的長度都是獨一無二的,而我們希望能夠按照特定長度查找字符串:
```
<pre class="calibre11">```
ImmutableMap<Integer, String> stringsByIndex = Maps.uniqueIndex(strings,
new Function<String, Integer> () {
public Integer apply(String string) {
return string.length();
}
});
```
```
如果索引值不是獨一無二的,請參見下面的Multimaps.index方法。
### difference
[`Maps.difference(Map, Map)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#difference%28java.util.Map,%20java.util.Map%29)用來比較兩個Map以獲取所有不同點。該方法返回MapDifference對象,把不同點的維恩圖分解為:
[`entriesInCommon()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapDifference.html#entriesInCommon%28%29)兩個Map中都有的映射項,包括匹配的鍵與值[`entriesDiffering()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapDifference.html#entriesDiffering%28%29)鍵相同但是值不同值映射項。返回的Map的值類型為[`MapDifference.ValueDifference`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapDifference.ValueDifference.html),以表示左右兩個不同的值[`entriesOnlyOnLeft()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapDifference.html#entriesOnlyOnLeft%28%29)鍵只存在于左邊Map的映射項[`entriesOnlyOnRight()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/MapDifference.html#entriesOnlyOnRight%28%29)鍵只存在于右邊Map的映射項```
<pre class="calibre11">```
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類中,因為BiMap也是一種Map實現。
**BiMap\*\***工具方法\*\***相應的\*\***Map**\*\*工具方法**[`synchronizedBiMap(BiMap)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6common/collect/Maps.html#synchronizedBiMap%28com.google.common.collect.BiMap%29)Collections.synchronizedMap(Map)[`unmodifiableBiMap(BiMap)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6common/collect/Maps.html#unmodifiableBiMap%28com.google.common.collect.BiMap%29)Collections.unmodifiableMap(Map)### 靜態工廠方法
Maps提供如下靜態工廠方法:
**具體實現類型****工廠方法**HashMap[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newHashMap%28%29), [from `Map`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newHashMap%28java.util.Map%29), [with expected size](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newHashMapWithExpectedSize%28int%29)LinkedHashMap[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newLinkedHashMap%28%29), [from `Map`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newLinkedHashMap%28java.util.Map%29)TreeMap[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newTreeMap%28%29), [from `Comparator`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newTreeMap%28java.util.Comparator%29), [from `SortedMap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newTreeMap%28java.util.SortedMap%29)EnumMap[from `Class`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newEnumMap%28java.lang.Class%29), [from `Map`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newEnumMap%28java.util.Map%29)ConcurrentMap:支持所有操作[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newConcurrentMap%28%29)IdentityHashMap[basic](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Maps.html#newIdentityHashMap%28%29)## Multisets
標準的Collection操作會忽略Multiset重復元素的個數,而只關心元素是否存在于Multiset中,如containsAll方法。為此,[`Multisets`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/Multisets.html)提供了若干方法,以顧及Multiset元素的重復性:
**方法****說明****和\*\***Collection**\*\*方法的區別**[`containsOccurrences(Multiset sup, Multiset sub)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6lect/Multisets.html#containsOccurrences%28com.google.common.collect.Multiset,%20com.google.common.collect.Multiset%29)對任意o,如果sub.count(o)<=super.count(o),返回trueCollection.containsAll忽略個數,而只關心sub的元素是否都在super中[`removeOccurrences(Multiset removeFrom, Multiset toRemove)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ollect/Multisets.html#removeOccurrences%28com.google.common.collect.Multiset,%20com.google.common.collect.Multiset%29)對toRemove中的重復元素,僅在removeFrom中刪除相同個數。Collection.removeAll移除所有出現在toRemove的元素[`retainOccurrences(Multiset removeFrom, Multiset toRetain)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ollect/Multisets.html#retainOccurrences%28com.google.common.collect.Multiset,%20com.google.common.collect.Multiset%29)修改removeFrom,以保證任意o都符合removeFrom.count(o)<=toRetain.count(o)Collection.retainAll保留所有出現在toRetain的元素[`intersection(Multiset, Multiset)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6mon/collect/Multisets.html#intersection%28com.google.common.collect.Multiset,%20com.google.common.collect.Multiset%29)返回兩個multiset的交集;沒有類似方法```
<pre class="calibre11">```
Multiset<String> multiset1 = HashMultiset.create();
multiset1.add("a", 2);
Multiset<String> multiset2 = HashMultiset.create();
multiset2.add("a", 5);
multiset1.containsAll(multiset2); //返回true;因為包含了所有不重復元素,
//雖然multiset1實際上包含2個"a",而multiset2包含5個"a"
Multisets.containsOccurrences(multiset1, multiset2); // returns false
multiset2.removeOccurrences(multiset1); // multiset2 現在包含3個"a"
multiset2.removeAll(multiset1);//multiset2移除所有"a",雖然multiset1只有2個"a"
multiset2.isEmpty(); // returns true
```
```
Multisets中的其他工具方法還包括:
[`copyHighestCountFirst(Multiset)`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/co%E2%80%A6ct/Multisets.html#copyHighestCountFirst%28com.google.common.collect.Multiset%29)返回Multiset的不可變拷貝,并將元素按重復出現的次數做降序排列[`unmodifiableMultiset(Multiset)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ect/Multisets.html#unmodifiableMultiset%28com.google.common.collect.Multiset%29)返回Multiset的只讀視圖[`unmodifiableSortedMultiset(SortedMultiset)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6s.html#unmodifiableSortedMultiset%28com.google.common.collect.SortedMultiset%29)返回SortedMultiset的只讀視圖```
<pre class="calibre11">```
Multiset<String> 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"}排列元素
```
```
## Multimaps
[`Multimaps`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html)提供了若干值得單獨說明的通用工具方法
### index
作為Maps.uniqueIndex的兄弟方法,[`Multimaps.index(Iterable, Function)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#index%28java.lang.Iterable,%20com.google.common.base.Function%29)通常針對的場景是:有一組對象,它們有共同的特定屬性,我們希望按照這個屬性的值查詢對象,但屬性值不一定是獨一無二的。
比方說,我們想把字符串按長度分組。
```
<pre class="calibre11">```
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();
}
};
ImmutableListMultimap<Integer, String> digitsByLength= Multimaps.index(digits, lengthFunction);
/*
* digitsByLength maps:
* 3 => {"one", "two", "six"}
* 4 => {"zero", "four", "five", "nine"}
* 5 => {"three", "seven", "eight"}
*/
```
```
### invertFrom
鑒于Multimap可以把多個鍵映射到同一個值(*譯者注:實際上這是任何\_\_map都有的特性*),也可以把一個鍵映射到多個值,反轉Multimap也會很有用。Guava 提供了[`invertFrom(Multimap toInvert,Multimap dest)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ommon/collect/Multimaps.html#invertFrom(com.google.common.collect.Multimap,%20M))做這個操作,并且你可以自由選擇反轉后的Multimap實現。
注:如果你使用的是ImmutableMultimap,考慮改用[`ImmutableMultimap.inverse()`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableMultimap.html#inverse%28%29)做反轉。
```
<pre class="calibre11">```
ArrayListMultimap<String, Integer> 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<Integer, String> inverse = Multimaps.invertFrom(multimap, TreeMultimap<String, Integer>.create());
//注意我們選擇的實現,因為選了TreeMultimap,得到的反轉結果是有序的
/*
* inverse maps:
* 1 => {"a"}
* 2 => {"a", "b", "c"}
* 3 => {"c"}
* 4 => {"a", "b"}
* 5 => {"c"}
* 6 => {"b"}
*/
```
```
### forMap
想在Map對象上使用Multimap的方法嗎?[`forMap(Map)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#forMap%28java.util.Map%29)把Map包裝成SetMultimap。這個方法特別有用,例如,與Multimaps.invertFrom結合使用,可以把多對一的Map反轉為一對多的Multimap。
```
<pre class="calibre11">```
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}]
Multimap<Integer, String> inverse = Multimaps.invertFrom(multimap, HashMultimap<Integer, String>.create());
// inverse:[1 => {"a","b"}, 2 => {"c"}]
```
```
### 包裝器
Multimaps提供了傳統的包裝方法,以及讓你選擇Map和Collection類型以自定義Multimap實現的工具方法。
只讀包裝[`Multimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ect/Multimaps.html#unmodifiableMultimap%28com.google.common.collect.Multimap%29)[`ListMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6imaps.html#unmodifiableListMultimap%28com.google.common.collect.ListMultimap%29)[`SetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ltimaps.html#unmodifiableSetMultimap%28com.google.common.collect.SetMultimap%29)[`SortedSetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6#unmodifiableSortedSetMultimap%28com.google.common.collect.SortedSetMultimap%29)同步包裝[`Multimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ect/Multimaps.html#synchronizedMultimap%28com.google.common.collect.Multimap%29)[`ListMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6imaps.html#synchronizedListMultimap%28com.google.common.collect.ListMultimap%29)[`SetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6ltimaps.html#synchronizedSetMultimap%28com.google.common.collect.SetMultimap%29)[`SortedSetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6#synchronizedSortedSetMultimap%28com.google.common.collect.SortedSetMultimap%29)自定義實現[`Multimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#newMultimap%28java.util.Map,%20com.google.common.base.Supplier%29)[`ListMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#newListMultimap%28java.util.Map,%20com.google.common.base.Supplier%29)[`SetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#newSetMultimap%28java.util.Map,%20com.google.common.base.Supplier%29)[`SortedSetMultimap`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Multimaps.html#newSortedSetMultimap%28java.util.Map,%20com.google.common.base.Supplier%29)自定義Multimap的方法允許你指定Multimap中的特定實現。但要注意的是:
- Multimap假設對Map和Supplier產生的集合對象有完全所有權。這些自定義對象應避免手動更新,并且在提供給Multimap時應該是空的,此外還不應該使用軟引用、弱引用或虛引用。
- 無法保證修改了Multimap以后,底層Map的內容是什么樣的。
- 即使Map和Supplier產生的集合都是線程安全的,它們組成的Multimap也不能保證并發操作的線程安全性。并發讀操作是工作正常的,但需要保證并發讀寫的話,請考慮用同步包裝器解決。
- 只有當Map、Supplier、Supplier產生的集合對象、以及Multimap存放的鍵值類型都是可序列化的,Multimap才是可序列化的。
- Multimap.get(key)返回的集合對象和Supplier返回的集合對象并不是同一類型。但如果Supplier返回的是隨機訪問集合,那么Multimap.get(key)返回的集合也是可隨機訪問的。
請注意,用來自定義Multimap的方法需要一個Supplier參數,以創建嶄新的集合。下面有個實現ListMultimap的例子——用TreeMap做映射,而每個鍵對應的多個值用LinkedList存儲。
```
<pre class="calibre11">```
ListMultimap<String, Integer> myMultimap = Multimaps.newListMultimap(
Maps.<String, Collection>newTreeMap(),
new Supplier<LinkedList>() {
public LinkedList get() {
return Lists.newLinkedList();
}
});
```
```
## Tables
[`Tables`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Tables.html)類提供了若干稱手的工具方法。
### 自定義Table
堪比Multimaps.newXXXMultimap(Map, Supplier)工具方法,[`Tables.newCustomTable(Map, Supplier<Map>)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Tables.html#newCustomTable%28java.util.Map,%20com.google.common.base.Supplier%29)允許你指定Table用什么樣的map實現行和列。
```
<pre class="calibre11">```
// 使用LinkedHashMaps替代HashMaps
Table<String, Character, Integer> table = Tables.newCustomTable(
Maps.<String, Map<Character, Integer>>newLinkedHashMap(),
new Supplier<Map<Character, Integer>> () {
public Map<Character, Integer> get() {
return Maps.newLinkedHashMap();
}
});
```
```
### transpose
[`transpose(Table<R, C, V>)`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/Tables.html#transpose%28com.google.common.collect.Table%29)方法允許你把Table<C, R, V>轉置成Table<R, C, V>。例如,如果你在用Table構建加權有向圖,這個方法就可以把有向圖反轉。
### 包裝器
還有很多你熟悉和喜歡的Table包裝類。然而,在大多數情況下還請使用[`ImmutableTable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/google/common/collect/ImmutableTable.html)
Unmodifiable[`Table`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6mmon/collect/Tables.html#unmodifiableTable%28com.google.common.collect.Table%29)[`RowSortedTable`](http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/com/%E2%80%A6s.html#unmodifiableRowSortedTable%28com.google.common.collect.RowSortedTable%29)
- 介紹
- Google Guava官方教程(中文版)
- 1-基本工具
- 1.1-使用和避免null
- 1.2-前置條件
- 1.3-常見Object方法
- 1.4-排序: Guava強大的”流暢風格比較器”
- 1.5-Throwables:簡化異常和錯誤的傳播與檢查
- 2-集合
- 2.1-不可變集合
- 2.2-新集合類型
- 2.3-強大的集合工具類:java.util.Collections中未包含的集合工具
- 2.4-集合擴展工具類
- 3-緩存
- 4-函數式編程
- 5-并發
- 5.1-google Guava包的ListenableFuture解析
- 5.2-Google-Guava Concurrent包里的Service框架淺析
- 6-字符串處理:分割,連接,填充
- 7-原生類型
- 9-I/O
- 10-散列
- 11-事件總線
- 12-數學運算
- 13-反射