Guava記錄 - 新集合類型Multimap

一、簡介

Multimap是一種將鍵與任意多個值相關(guān)聯(lián)的通用方法。
官網(wǎng)對其的描述如下:

Every experienced Java programmer has, at one point or another, implemented a Map<K, List<V>> or Map<K, Set<V>>, and dealt with the awkwardness of that structure. For example, Map<K, Set<V>> is a typical way to represent an unlabeled directed graph. Guava's Multimap framework makes it easy to handle a mapping from keys to multiple values. A Multimap is a general way to associate keys with arbitrarily many values.

大致意思為:咱每個有經(jīng)驗的程序員都基本都實現(xiàn)過Map<K, List<V>> 或者Map<K, Set<V>>并處理對應(yīng)業(yè)務(wù).但是這種結(jié)構(gòu)很笨拙.而Guava的Multimap會使得操作這種映射關(guān)系更容易.

有兩種方法可以從概念上理解多Multimap

1、一個key對應(yīng)一個值:

a -> 1
a -> 2
a -> 4
b -> 3
c -> 5

2、一個key對應(yīng)一個集合

a -> [1, 2, 4]
b -> [3]
c -> [5]

通常情況下來說最好是使用第一種方式,但是也可以通過asMap的方式返回一個Map<K, List<V>> .
最重要的是,這里不會存在一個key映射到一個空集合.
在Multimap中一個key要么至少有一個值,要么就不存在.
但是我們很少直接使用Multimap接口,更多的是使用ListMultimap或者Setultimap接口,它們分別把鍵映射到list或者set上.

二、如何構(gòu)建Multimap?

官網(wǎng)給的最直接的創(chuàng)建例子如下:它允許你如何配置表表示對應(yīng)的key和value.

    // creates a ListMultimap with tree keys and array list values
    ListMultimap<String, Integer> treeListMultimap =
    MultimapBuilder.treeKeys().arrayListValues().build();

    // creates a SetMultimap with hash keys and enum set values
    SetMultimap<Integer, MyEnum> hashEnumMultimap =
    MultimapBuilder.hashKeys().enumSetValues(MyEnum.class).build();

也可以使用create()的方式進行創(chuàng)建,但是是不鼓勵這樣做的.部分Multimap對象創(chuàng)建如下:

        //通過create方式創(chuàng)建.但是官方是不鼓勵的

        //通過create方式 - 創(chuàng)建ArrayListMultimap對象
        Multimap<String, String> multimap = ArrayListMultimap.create();
        
        //通過create方式 - 創(chuàng)建HashMultimap對象
        Multimap<String, String> hashMultimap = HashMultimap.create();
        
        //通過create方式 - 創(chuàng)建LinkedHashMultimap對象
        Multimap<String, String> linkedHashMultimap = LinkedHashMultimap.create();
        
        //通過create方式 - 創(chuàng)建LinkedListMultimap對象
        Multimap<String, String> linkedListMultimap = LinkedListMultimap.create();
        
        //通過create方式 - 創(chuàng)建TreeMultimap對象
        Multimap<String, String> treeMultimap = TreeMultimap.create();
        
        //創(chuàng)建ImmutableListMultimap對象
        Multimap<String, String> immutableListMultimap = ImmutableListMultimap.of();
        
        //通過create方式 - 創(chuàng)建TreeMultimap對象
        Multimap<String, String> immutableSetMultimap = ImmutableSetMultimap.of();

三、常用方法

1、修改類型的方法 - Modifying
a、put(K, V)方法

添加一個k - v 映射
put(K, V)等價于multimap.get(key).add(value).

實驗代碼:

        ListMultimap<String, Integer> treeListMultimap =
                MultimapBuilder.treeKeys().arrayListValues().build();
        treeListMultimap.put("ListA", 1);
        treeListMultimap.put("ListA", 2);
        treeListMultimap.put("ListA", 3);
        //以上的put方式等價于 - xxxxMap.get().add()方式
        treeListMultimap.get("ListB").add(4);

        System.out.println("==================ListMultimap=====gasMap方法值====" + treeListMultimap.asMap());

        輸出:==================ListMultimap=====get方法值===={ListA=[1, 2, 3], ListB=[4]}
b、putAll(k, Iterable<V>)方法

批量添加k - v數(shù)據(jù),等同于Iterables.addAll(multimap.get(key), values)

實驗代碼:

        //test put all - 等價于Iterables.addAll
        treeListMultimap.putAll("ListC", dataList);
        //等價于put all
        Iterables.addAll(treeListMultimap.get("ListC"), dataList);
        System.out.println("==================ListMultimap=====gasMap方法值====" + treeListMultimap.asMap());

        輸出:==================ListMultimap=====get方法值===={ListA=[1, 2, 3], ListB=[4], ListC=[2001, 2002, 2003, 2001, 2002, 2003]}
c、remove(k, v)方法

從鍵到值刪除一個關(guān)聯(lián),如果multimap改變則返回true。
等價于multimap.get(key).remove(value).
removeAll的縮小版本.

實驗代碼:

        treeListMultimap.remove("ListA",1);
        System.out.println("==================ListMultimap==remove之后===get方法值====" + treeListMultimap.get("ListA"));

        輸出:==================ListMultimap==remove之后===get方法值====[2, 3]
d、removeAll(K)方法

刪除并返回與指定鍵關(guān)聯(lián)的所有值。返回的集合可以修改,也可以不修改,但是修改它不會影響multimap
實驗代碼:

        treeListMultimap.removeAll("ListA");
        System.out.println("==================ListMultimap==removeAll之后===get方法值====" + treeListMultimap.get("ListA"));
        
        輸出:==================ListMultimap==removeAll之后===get方法值====[]
e、replaceValues(k, Iterable<V>)方法

清除與鍵關(guān)聯(lián)的所有值,并設(shè)置與每個值關(guān)聯(lián)的鍵。返回以前與鍵關(guān)聯(lián)的值。

實驗代碼:

        treeListMultimap.replaceValues("ListsB",Lists.newArrayList(101,201));
        System.out.println("==================ListMultimap==replaceValues之后===get方法值====" + treeListMultimap.get("ListsB"));

        輸出:  ==================ListMultimap==replaceValues之后===get方法值====[101, 201]
2、查詢類型的方法 - Views
a、asMap()方法

將Multimap視圖以map的視圖形式返回.
返回的試圖支持修改,但是不支持put()以及putAll()方法.

實驗的代碼:

        Map<String, Collection<Integer>> testAsMap = treeListMultimap.asMap();
        testAsMap.remove("ListA");
        System.out.println("==================測試asMap======remove方法后========="+testAsMap);

        //測試put
        testAsMap.put("ListD", Lists.newArrayList(301));
        //測試putAll
        testAsMap.putAll(Maps.newHashMap());

實驗結(jié)果:

==================測試asMap======remove方法后========={ListB=[4], ListC=[2001, 2002, 2003, 2001, 2002, 2003], ListsB=[101, 201]}
java.lang.UnsupportedOperationException
    at java.util.AbstractMap.put(AbstractMap.java:209)
    at com.toxic.anepoch.guava.parsing.collection.newtypes.TestMultimap.main(TestMultimap.java:60)
b、entries()方法

返回當前multiMap的映射關(guān)系.

實驗代碼:

        System.out.println("==============測試MultiMap的entries()方法=============="+treeListMultimap.entries());
        輸出:==============測試MultiMap的entries()方法==============[ListB=4, ListC=2001, ListC=2002, ListC=2003, ListC=2001, ListC=2002, ListC=2003, ListsB=101, ListsB=201]
c、keySet()

返回當前MultiMap的key - set集合

實驗代碼:

        System.out.println("==============測試MultiMap的keySet()方法=============="+treeListMultimap.keySet());
        輸出:==============測試MultiMap的keySet()方法==============[ListB, ListC, ListsB]
d、keys()

返回當前MultiMap的MultiSet視圖

實驗代碼:

        System.out.println("==============測試MultiMap的keys()方法=============="+treeListMultimap.keys());
        輸出:==============測試MultiMap的keys()方法==============[ListB, ListC x 6, ListsB x 2]
e、values()

返回當前MultiMap拍平了的value - collection集合

實驗代碼:

        System.out.println("==============測試MultiMap的values()方法=============="+treeListMultimap.values());
        輸出:==============測試MultiMap的values()方法==============[4, 2001, 2002, 2003, 2001, 2002, 2003, 101, 201]

四、最后值得注意的是MultiMap并不是一個map

感興趣的可以了解一下
官網(wǎng)描述:

A Multimap<K, V> is not a Map<K, Collection<V>>, though such a map might be used in a Multimap implementation. Notable differences include:

  • Multimap.get(key) always returns a non-null, possibly empty collection. This doesn't imply that the multimap spends any memory associated with the key, but instead, the returned collection is a view that allows you to add associations with the key if you like.
  • If you prefer the more Map-like behavior of returning null for keys that aren't in the multimap, use the asMap() view to get a Map<K, Collection<V>>. (Or, to get a Map<K,List<V>> from a ListMultimap, use the static Multimaps.asMap() method. Similar methods exist for SetMultimap and SortedSetMultimap.)
  • Multimap.containsKey(key) is true if and only if there are any elements associated with the specified key. In particular, if a key k was previously associated with one or more values which have since been removed from the multimap, Multimap.containsKey(k) will return false.
  • Multimap.entries() returns all entries for all keys in the Multimap. If you want all key-collection entries, use asMap().entrySet().
  • Multimap.size() returns the number of entries in the entire multimap, not the number of distinct keys. Use Multimap.keySet().size() instead to get the number of distinct keys.

......未完待續(xù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容