簡化你的 java map 操做:Guava 之 Multimap 用法簡介

前不久在這篇 使用 Google Guava 美化你的 Java 代碼:1~4 中的 「一個集合統治一切 – Multimap」 部分提到過這貨,不過當時那篇文章受限於篇幅,例子舉的不夠詳盡,估計不少同窗看了仍是雲裏霧裏,一頭霧水。 html

說個具體的應用場景吧: java

好比如今我有一份日誌記錄,每條記錄的內容是一個 url 對應一個訪客的 userid,我如今想獲得 每一個 url 對應的 pv、uv 數據,你會怎麼作? git

普通青年通常這麼想的:用 url 作 key,userid 做爲對應 list 的內容: apache

Map<String,List<MyClass>> myClassListMap = new HashMap<String,List<MyClass>>()
而後你須要檢查key是否存在,不然建立一個,最後代碼成爲這個樣子: 
void putMyObject(String key, Object value) {
    List<Object> myClassList = myClassListMap.get(key);
    if(myClassList == null) {
        myClassList = new ArrayList<object>();
        myClassListMap.put(key,myClassList);
    }
    myClassList.add(value);
}

若是你但願檢查List中的對象是否存在,刪除一個對象,或者遍歷整個數據結構,那麼須要更多的代碼。  api

看到這裏不由感嘆一句:這特麼都什麼玩意啊。。。 數據結構

恩,懶人總有懶人的辦法,習慣腳本語言的我,很難忍受 java 的這種臃腫的代碼了,下面看看用以前提到的 Guava MultiMap 怎麼優雅的解決這個問題。 ui

Multimap<String,Object> myMultimap = ArrayListMultimap.create();
這裏須要注意,全部的guava的集合都有create()方法,這個好處就是比較簡單,你不用重複泛型信息了。 

好了,開始使用Multimap了:
google

package com.test;

import java.util.Collection;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;

public class MutliMapTest {
	public static void main(String... args) {
		Multimap<String, String> myMultimap = ArrayListMultimap.create();

		// Adding some key/value
		myMultimap.put("Fruits", "Bannana");
		myMultimap.put("Fruits", "Apple");
		myMultimap.put("Fruits", "Pear");
		myMultimap.put("Fruits", "Pear");
		myMultimap.put("Vegetables", "Carrot");

		// Getting the size
		int size = myMultimap.size();
		System.out.println(size); // 5

		// Getting values
		Collection<String> fruits = myMultimap.get("Fruits");
		System.out.println(fruits); //  [Bannana, Apple, Pear, Pear]
		System.out.println(ImmutableSet.copyOf(fruits));// [Bannana, Apple, Pear]
		// Set<Foo> set = Sets.newHashSet(list);
		// Set<Foo> foo = new HashSet<Foo>(myList);

		Collection<String> vegetables = myMultimap.get("Vegetables");
		System.out.println(vegetables); // [Carrot]

		// Iterating over entire Mutlimap
		for (String value : myMultimap.values()) {
			System.out.println(value);
		}

		// Removing a single value
		myMultimap.remove("Fruits", "Pear");
		System.out.println(myMultimap.get("Fruits")); // [Bannana, Apple, Pear]

		// Remove all values for a key
		myMultimap.removeAll("Fruits");
		System.out.println(myMultimap.get("Fruits")); // [] (Empty Collection!)
	}
}
這裏有一點你可能會疑惑,就是爲什麼get方法返回的是一個collection而不是list,這是由於前者會更加有用。若是你須要基於multimap直接操做list或者set,那麼可使用在定義類型的時候使用子類名稱:ListMultimap,SetMultimap和SortedSetMultimap。例如: 

ListMutlimap<String,String> myMutlimap = ArrayListMultimap.create();

List<string> myValues = myMutlimap.get("myKey");  // Returns a List, not a Collection.
好了,基本就是這樣,你能夠參考API獲取更多信息:

http://docs.guava-libraries.googlecode.com/git-history/release/javadoc/index.html url

PS: 下面再補充另外一個問題:如何判斷兩個集合是否存在交集? spa

(1)普通寫法:雙層 for 循環遍歷兩個集合

boolean found = false;
for(Object1 object1 : list1){
   for(Object2 object2: list2){
       if(object1.getAttributeSame() == object2.getAttributeSame()){
           found = true;
           break;
           //also do something
       }
    }
    if(!found){
        //do something
    }
    found = false;
}
(2)JDK 自帶的集合方法:disjoint
!Collections.disjoint(list1, list2);
(3) 使用第三方庫: Apache Commons CollectionUtils

http://commons.apache.org/proper/commons-collections/javadocs/api-release/index.html

if(CollectionUtils.containsAny(list1,list2)  
{  
    //do whatever
}  
else{ 
     //do other thing 
}
(4)不過高效的,可是簡潔可用的變通方法:retainAll
if (!new HashSet<T>(list1).retainAll(list2).isEmpty())
    // at least one element is shared

(5)順便說下如何求集合的包含、所屬關係:

public class Test {

	public static void main(String[] args) throws IOException {
		Set a = new HashSet() {
			{
				add(1);
				add(2);
			}
		};

		Set b = new HashSet() {
			{
				add(2);
				add(3);
				add(1);
			}
		};

		System.out.println(b.containsAll(a));
		System.out.println(CollectionUtils.containsAll(b, a));

	}

}

Ref:

http://stackoverflow.com/questions/11796371/check-if-one-list-contains-element-from-the-other

相關文章
相關標籤/搜索