文档章节

简化你的 java map 操作:Guava 之 Multimap 用法简介

大数据之路
 大数据之路
发布于 2013/11/28 03:44
字数 854
阅读 9721
收藏 25

前不久在这篇 使用 Google Guava 美化你的 Java 代码:1~4 中的 “一个集合统治一切 – Multimap” 部分提到过这货,不过当时那篇文章受限于篇幅,例子举的不够详尽,估计很多同学看了还是云里雾里,一头雾水。

说个具体的应用场景吧:

比如现在我有一份日志记录,每条记录的内容是一个 url 对应一个访客的 userid,我现在想得到 每个 url 对应的 pv、uv 数据,你会怎么做?

普通青年一般这么想的:用 url 做 key,userid 作为对应 list 的内容:

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中的对象是否存在,删除一个对象,或者遍历整个数据结构,那么需要更多的代码。 

看到这里不禁感叹一句:这特么都什么玩意啊。。。

恩,懒人总有懒人的办法,习惯脚本语言的我,很难忍受 java 的这种臃肿的代码了,下面看看用之前提到的 Guava MultiMap 怎么优雅的解决这个问题。

Multimap<String,Object> myMultimap = ArrayListMultimap.create();
这里需要注意,所有的guava的集合都有create()方法,这个好处就是比较简单,你不用重复泛型信息了。 

好了,开始使用Multimap了:

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

PS: 下面再补充另一个问题:如何判断两个集合是否存在交集?

(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


本文转载自:http://vipcowrie.iteye.com/blog/1517338

共有 人打赏支持
大数据之路
粉丝 1543
博文 516
码字总数 343694
作品 0
武汉
架构师
私信 提问
加载中

评论(1)

柳晴
柳晴
问个问题,怎么方便的对map的value排序 ?
使用 Google Guava 美化你的 Java 代码:1~4

1-使用 GOOGLE COLLECTIONS,GUAVA,STATIC IMPORTS 编写漂亮代码 写在前面: 以前在一个项目中用到过guava,当时匆匆用,也没细研究,今天偶然在occhina看到这个系列教程的翻译,感觉不错,介...

大数据之路
2013/10/28
0
7
Google Guava Collections 使用介绍

Google Guava Collections(以下都简称为 Guava Collections)是 Java Collections Framework 的增强和扩展。每个 Java 开发者都会在工作中使用各种数据结构,很多情况下 Java Collections F...

毒性逆转
2011/11/17
0
1
guava 学习笔记(二) 瓜娃(guava)的API快速熟悉使用

1,大纲 让我们来熟悉瓜娃,并体验下它的一些API,分成如下几个部分: Introduction Guava Collection API Guava Basic Utilities IO API Cache API 2,为神马选择瓜娃? 瓜娃是java API蛋糕上...

zmf
2015/09/04
0
0
Guava 教程1-使用 Google Collections,Guava,static imports 编写漂亮代码

这个夏天的早些时候,我已经极力向我的所有同事推荐了 Google Collections 。 Kevin Bourrillion说他的一个同事告诉他“没有使用Google Collections前编程就像把一只手绑在背后”。 我灰常同...

se77en
2013/01/30
10.7K
4
Google的Guava类库简介(转)

说明:信息虽然有点旧,至少可以先了解个大概。 Guava是一个Google的基于Java的类库集合的扩展项目,包括collections, caching, primitives support, concurrency libraries, common annotat...

easonjim
2017/11/01
0
0

没有更多内容

加载失败,请刷新页面

加载更多

序列化与反序列化实现

一、序列化和反序列化的概念 把对象转换为字节序列的过程称为对象的序列化。 把字节序列恢复为对象的过程称为对象的反序列化。 对象序列化之后得到的字节序列,主要有两种用途:   1) 把对...

狼王黄师傅
20分钟前
0
0
Spring boot 各种常用注解总结(不断完善中)

@Configuration把一个类作为一个IoC容器,它的某个方法头上如果注册了@Bean,就会作为这个Spring容器中的Bean。 @Scope注解 作用域 @Lazy(true) 表示延迟初始化 @Service用于标注业务层组件、...

覃大光
22分钟前
2
1
《让家庭教育回归生活》读书笔记3000字范文

《让家庭教育回归生活》读书笔记3000字范文: 以前,只知道新东方是教英语的,也培训挖掘机司机,一直不知道他们还研究家庭教育。读了《让家庭教育回归生活》一书,才知道他们的家庭教育高峰...

原创小博客
34分钟前
3
0
spring学习笔记(二)spring 事件的使用

spring 中的事件 spring事件通过订阅发布 可以解耦操作 可以同步 可以异步 步骤 编写事件 通过继承org.springframework.context.ApplicationEvent 来编写事件 public ApplicationEvent(Obj...

NotFound403
昨天
15
0
特斯拉车主成功破解了自己Model 3汽车

据汽车博客Electrek消息,一位特斯拉车主成功破解了自己Model 3汽车,还在此基础上运行了Ubuntu。 这位叫trsohmers的网友表示,“功劳大多要归到Ingineerix的头上,他花了数月才找到初始的那...

linuxCool
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部