尚未完成: Queues, Tables 工具類
任何對(duì) JDK 集合框架有經(jīng)驗(yàn)的程序員都熟悉和喜歡 java.util.Collections 包含的工具方法。Guava 沿著這些路線提供了更多的工具方法:適用于所有集合的靜態(tài)方法。這是 Guava 最流行和成熟的部分之一。
我們用相對(duì)直觀的方式把工具類與特定集合接口的對(duì)應(yīng)關(guān)系歸納如下:
集合接口 | 屬于JDK還是Guava | 對(duì)應(yīng)的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 |
在找類似轉(zhuǎn)化、過濾的方法?請(qǐng)看第四章,函數(shù)式風(fēng)格。
在 JDK 7之前,構(gòu)造新的范型集合時(shí)要討厭地重復(fù)聲明范型:
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<TypeThatsTooLongForItsOwnGood>();
我想我們都認(rèn)為這很討厭。因此 Guava 提供了能夠推斷范型的靜態(tài)工廠方法:
List<TypeThatsTooLongForItsOwnGood> list = Lists.newArrayList();
Map<KeyType, LongishValueType> map = Maps.newLinkedHashMap();
可以肯定的是,JDK7 版本的鉆石操作符(<>)沒有這樣的麻煩:
List<TypeThatsTooLongForItsOwnGood> list = new ArrayList<>();
但 Guava 的靜態(tài)工廠方法遠(yuǎn)不止這么簡(jiǎn)單。用工廠方法模式,我們可以方便地在初始化時(shí)就指定起始元素。
Set<Type> 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<String> multiset = HashMultiset.create();
在可能的情況下,Guava 提供的工具方法更偏向于接受 Iterable 而不是 Collection 類型。在 Google,對(duì)于不存放在主存的集合——比如從數(shù)據(jù)庫或其他數(shù)據(jù)中心收集的結(jié)果集,因?yàn)閷?shí)際上還沒有攫取全部數(shù)據(jù),這類結(jié)果集都不能支持類似 size()的操作 ——通常都不會(huì)用 Collection 類型來表示。
因此,很多你期望的支持所有集合的操作都在 Iterables 類中。大多數(shù) Iterables 方法有一個(gè)在 Iterators 類中的對(duì)應(yīng)版本,用來處理 Iterator。
截至 Guava 1.2 版本,Iterables 使用 FluentIterable 類進(jìn)行了補(bǔ)充,它包裝了一個(gè) Iterable 實(shí)例,并對(duì)許多操作提供了”fluent”(鏈?zhǔn)秸{(diào)用)語法。
下面列出了一些最常用的工具方法,但更多 Iterables 的函數(shù)式方法將在第四章討論。
concat(Iterable<Iterable>) | 串聯(lián)多個(gè) iterables 的懶視圖* | concat(Iterable...) |
frequency(Iterable, Object) | 返回對(duì)象在 iterable 中出現(xiàn)的次數(shù) | 與 Collections.frequency (Collection, Object)比較;Multiset |
partition(Iterable, int) | 把 iterable 按指定大小分割,得到的子集都不能進(jìn)行修改操作 | Lists.partition(List, int);paddedPartition(Iterable, int) |
getFirst(Iterable, T default) | 返回 iterable 的第一個(gè)元素,若 iterable 為空則返回默認(rèn)值 | 與Iterable.iterator(). next()比較;FluentIterable.first() |
getLast(Iterable) | 返回 iterable 的最后一個(gè)元素,若 iterable 為空則拋出NoSuchElementException |
getLast(Iterable, T default); FluentIterable.last() |
elementsEqual(Iterable, Iterable) | 如果兩個(gè) iterable 中的所有元素相等且順序一致,返回 true | 與 List.equals(Object)比較 |
unmodifiableIterable(Iterable) | 返回 iterable 的不可變視圖 | 與 Collections. unmodifiableCollection(Collection)比較 |
limit(Iterable, int) | 限制 iterable 的元素個(gè)數(shù)限制給定值 | FluentIterable.limit(int) |
getOnlyElement(Iterable) | 獲取 iterable 中唯一的元素,如果 iterable 為空或有多個(gè)元素,則快速失敗 | getOnlyElement(Iterable, T default) |
譯者注:懶視圖意味著如果還沒訪問到某個(gè) iterable 中的元素,則不會(huì)對(duì)它進(jìn)行串聯(lián)操作。
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不是單元素集,就會(huì)出錯(cuò)了!
通常來說,Collection 的實(shí)現(xiàn)天然支持操作其他 Collection,但卻不能操作 Iterable。
下面的方法中,如果傳入的 Iterable 是一個(gè) Collection 實(shí)例,則實(shí)際操作將會(huì)委托給相應(yīng)的 Collection 接口方法。例如,往 Iterables.size 方法傳入是一個(gè) Collection 實(shí)例,它不會(huì)真的遍歷 iterator 獲取大小,而是直接調(diào)用 Collection.size。
方法 | 類似的 Collection 方法 | 等價(jià)的 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() |
除了上面和第四章提到的方法,F(xiàn)luentIterable 還有一些便利方法用來把自己拷貝到不可變集合
ImmutableList | |
ImmutableSet | toImmutableSet() |
ImmutableSortedSet | toImmutableSortedSet(Comparator) |
除了靜態(tài)工廠方法和函數(shù)式編程方法,Lists 為 List 類型的對(duì)象提供了若干工具方法。
方法 | 描述 |
partition(List, int) | 把 List 按指定大小分割 |
reverse(List) | 返回給定 List 的反轉(zhuǎn)視圖。注: 如果 List 是不可變的,考慮改用 ImmutableList.reverse()。 |
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 提供如下靜態(tài)工廠方法:
具體實(shí)現(xiàn)類型 | 工廠方法 |
ArrayList | basic, with elements, from Iterable, with exact capacity, with expected size, from Iterator |
LinkedList | basic, from Iterable |
Sets 工具類包含了若干好用的方法。
我們提供了很多標(biāo)準(zhǔn)的集合運(yùn)算(Set-Theoretic)方法,這些方法接受 Set 參數(shù)并返回 SetView,可用于:
方法 |
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();//可以使用交集,但不可變拷貝的讀取效率更高
方法 | 描述 | 另請(qǐng)參見 |
cartesianProduct(List<Set>) | 返回所有集合的笛卡兒積 | cartesianProduct(Set...) |
powerSet(Set) | 返回給定集合的所有子集 |
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 提供如下靜態(tài)工廠方法:
具體實(shí)現(xiàn)類型 | 工廠方法 |
HashSet | basic, with elements, from Iterable, with expected size, from Iterator |
LinkedHashSet | basic, from Iterable, with expected size |
TreeSet | basic, with Comparator, from Iterable |
Maps 類有若干值得單獨(dú)說明的、很酷的方法。
uniqueIndex
Maps.uniqueIndex(Iterable,Function) 通常針對(duì)的場(chǎng)景是:有一組對(duì)象,它們?cè)谀硞€(gè)屬性上分別有獨(dú)一無二的值,而我們希望能夠按照這個(gè)屬性值查找對(duì)象——譯者注:這個(gè)方法返回一個(gè) Map,鍵為 Function 返回的屬性值,值為 Iterable 中相應(yīng)的元素,因此我們可以反復(fù)用這個(gè) Map 進(jìn)行查找操作。
比方說,我們有一堆字符串,這些字符串的長(zhǎng)度都是獨(dú)一無二的,而我們希望能夠按照特定長(zhǎng)度查找字符串:
ImmutableMap<Integer, String> stringsByIndex = Maps.uniqueIndex(strings,
new Function<String, Integer> () {
public Integer apply(String string) {
return string.length();
}
});
如果索引值不是獨(dú)一無二的,請(qǐng)參見下面的 Multimaps.index 方法。
difference
Maps.difference(Map, Map) 用來比較兩個(gè) Map 以獲取所有不同點(diǎn)。該方法返回 MapDifference 對(duì)象,把不同點(diǎn)的維恩圖分解為:
entriesInCommon() | 兩個(gè) Map 中都有的映射項(xiàng),包括匹配的鍵與值 |
entriesDiffering() | 鍵相同但是值不同值映射項(xiàng)。返回的 Map 的值類型為 MapDifference.ValueDifference,以表示左右兩個(gè)不同的值 |
entriesOnlyOnLeft() | 鍵只存在于左邊 Map 的映射項(xiàng) |
entriesOnlyOnRight() | 鍵只存在于右邊 Map 的映射項(xiàng) |
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}
Guava 中處理 BiMap 的工具方法在 Maps 類中,因?yàn)?BiMap 也是一種 Map 實(shí)現(xiàn)。
BiMap工具方法 | 相應(yīng)的 Map 工具方法 |
synchronizedBiMap(BiMap) | Collections.synchronizedMap(Map) |
unmodifiableBiMap(BiMap) | Collections.unmodifiableMap(Map) |
Maps 提供如下靜態(tài)工廠方法:
具體實(shí)現(xiàn)類型 | 工廠方法 |
HashMap | basic, from Map, with expected size |
LinkedHashMap | basic, from Map |
TreeMap | basic, from Comparator, from SortedMap |
EnumMap | from Class, from Map |
ConcurrentMap:支持所有操作 | basic |
IdentityHashMap | basic |