鍍金池/ 教程/ Java/ 強(qiáng)大的集合工具類:java.util.Collections 中未包含的集合工具
不可變集合
排序: Guava 強(qiáng)大的”流暢風(fēng)格比較器”
強(qiáng)大的集合工具類:java.util.Collections 中未包含的集合工具
新集合類型
常見 Object 方法
I/O
前置條件
字符串處理:分割,連接,填充
散列
原生類型
數(shù)學(xué)運(yùn)算
使用和避免 null
Throwables:簡(jiǎn)化異常和錯(cuò)誤的傳播與檢查
google Guava 包的 ListenableFuture 解析
事件總線
緩存
函數(shù)式編程
區(qū)間
集合擴(kuò)展工具類
Google-Guava Concurrent 包里的 Service 框架淺析
google Guava 包的 reflection 解析

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

 尚未完成: 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)格。

靜態(tài)工廠方法

在 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();

Iterables

在可能的情況下,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ù)式方法將在第四章討論。

常規(guī)方法

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 方法相似的工具方法

通常來說,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()

FluentIterable

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

ImmutableList
ImmutableSet toImmutableSet()
ImmutableSortedSet toImmutableSortedSet(Comparator)

Lists

除了靜態(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}}

靜態(tài)工廠方法

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

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();//可以使用交集,但不可變拷貝的讀取效率更高

其他 Set 工具方法

方法 描述 另請(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"}}

靜態(tài)工廠方法

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

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}

處理 BiMap 的工具方法

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

BiMap工具方法 相應(yīng)的 Map 工具方法
synchronizedBiMap(BiMap) Collections.synchronizedMap(Map)
unmodifiableBiMap(BiMap) Collections.unmodifiableMap(Map)

靜態(tài)工廠方法

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

上一篇:不可變集合下一篇:新集合類型