前不久在这篇 使用 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