一、簡介
Multimap是一種將鍵與任意多個值相關(guān)聯(lián)的通用方法。
官網(wǎng)對其的描述如下:
Every experienced Java programmer has, at one point or another, implemented a
Map<K, List<V>>orMap<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'sMultimapframework makes it easy to handle a mapping from keys to multiple values. AMultimapis 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 aMap<K, Collection<V>>, though such a map might be used in aMultimapimplementation. 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 returningnullfor keys that aren't in the multimap, use theasMap()view to get aMap<K, Collection<V>>. (Or, to get aMap<K,List<V>>from aListMultimap, use the staticMultimaps.asMap()method. Similar methods exist forSetMultimapandSortedSetMultimap.) -
Multimap.containsKey(key)is true if and only if there are any elements associated with the specified key. In particular, if a keykwas 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 theMultimap. If you want all key-collection entries, useasMap().entrySet(). -
Multimap.size()returns the number of entries in the entire multimap, not the number of distinct keys. UseMultimap.keySet().size()instead to get the number of distinct keys.
......未完待續(xù)