Guava 教程(4):条件,多重映射和分片
在本系列博客的前三章,我们大概介绍了Google的Guava类库和Collections类库,作为一名Java开发人员,相信你会从使用这些类库,进而来减少在你项目中使用样板文件的数量而获益。在本系列博客的最后一篇中,我将带大家来了解一个会让你完全爱上并沉浸于其中的的集合工具类-Multimap。我们将带大家了解下如何使用Google Collections的Preconditions来做校验,但是在此之前,先让我们来了解下如何对Set和Map进行交集、并集和差集的运算。
Set的交集,并集和map的相关操作
有时,当我们需要去对两个Set的取交集、并集和差集的时候,那是一件相关麻烦的事情,而且代码看起来很凌乱。经常情况,你会以一遍又一遍的循环来结束这种做法。但是如果我们使用Google Collections提供的Sets类就可以轻而易举的完成这些操作,并且是完全免费的!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
HashSet 1 , 2 , 3 , 4 , 5 ); HashSet 4 , 5 , 6 , 7 , 8 ); SetView System.out.println( "union:" ); for
System.out.println(integer); SetView System.out.println( "difference:" ); for
System.out.println(integer); SetView System.out.println( "intersection:" ); for
System.out.println(integer); |
From the Public Object
blog:
“不同于惯例,这些方法没有做任何的拷贝。相反,他们返回了代表了这两个集合的视图。 但是在有些情况下,这些拷贝又很有用,我们可以用immutableCopy类中提供的一个便利方法来实现拷贝”
同样地,对于Map而言,我们可以像下面这样处理:
1
|
MapDifference |
如果用MapDifference类,我们还可以这样:
1
2
3
4
5
|
differenceMap.areEqual(); Map Map Map Map |
Thank you, Google Collections
用Preconditions进行校验
早在初夏的时候,一个叫刚刚加入我们的同事Bent André向我介绍了用Preconditions进行校验的想法,但是,直到最近我才发现Google Collections实际上已经包含了相应的实现(我们自己也已经有了相似的实现)。
那么这个实现具体是什么样子的呢?校验就是要求我们准确无误的做一些事情,通常情况下,它看起来就是类似下面这样的代码:
1
2
3
|
if
0 ) throw
"must
} |
我们想校验调用我们的方法的方法传参是否正确,如果错了,应该发出一个“他出错了”的警告信息。
Java文档中是这样解释的:
“Precondition异常通常表示被调用方法发生了一个错误。它告诉调用者不能用这种方式、这种参数或者其它来调用这个方法。Postcondition或其它运行失败是不会抛出这种类型的异常的。”
因此用Preconditions类或者静态导入,我们就可以用下面这行简单的代码来替代上面那些的冗长的代码了:
1
|
checkArgument(count 0 , "must , |
同样,该类里还有其它类似的方法来检验状态和空值。
1
|
checkNotNull(entry); |
相当简洁,不是么?
“请注意这里是相反的表达(译者注:应该指的是checkNotNull中有not的意思,所以是相反的); 你用Preconditions声明什么是你期望返回true的,就好像你在Java中运用断言,或者在JUnit中调用assertTrue方法一样。”
From the excellent blog
series on Google Collections over at Public Object:
“Preconditions提供对方法状态的校验。它能使你输入的参数如你所期望的的那样足够简洁,与Java内建的断言不同的是Preconditions是一直开启的。”
下面是我在Integrasco上翻遍我所有的代码中,找到的一个比较好的例子:
1
2
3
4
5
6
7
8
9
|
public
final
final
final
//some //some //some this .title this .date this .author } |
用了Preconditions之后我们再来看看代码变得有多工整:
1
2
3
4
5
|
public
final
final
final
this .title this .date this .author } |
很简洁,不是么?
稍后我们会发表一篇关于异常和校验的更详细的文章,敬请关注!
一个集合统治一切 – Multimap
我已经数不清我有多少次需要在一个Map中实现一个key对应多个value的需求,最终不得不以Map<K, List<V>>这种结构来实现的经历了。
并且用这种方式实现一键多值的需求还存在很大的争议,如下所示:
1
2
3
4
5
6
7
8
9
10
|
Map<Person, new
public
final
final
List<BlogPost> if
null ) blogPosts new
map.put(author, } blogPosts.add(blogPost); } |
别告诉你你从来没这样做过?利用Google Collections中的Multimap类我们可以轻松实现上述需求,而且感觉很时髦(我很开心我可以这样表达):
1
2
3
4
5
|
Multimap<Person, public
final
final
multimap.put(author, } |
Whoop, whoop!
Google Collections提供了多种Multimaps的实现,如果你想防止出现键值对,可以用HashMultimap;如果你需要键值对按照自然顺序排列,你可以使用TreeMultimap;甚至你想按插入顺序来遍历集合,LinkedHashMultimap可以满足你的需求。
Multimaps同样提供了很多有用的方法,详细内容可以参考Multimap 和 Multimaps的API文档!
很激动是么?那就继续往下看吧…
分片集合
我管这节叫分片,相信很多人会觉得叫我们在之前文章叫提到的“过滤集合”更准确。但是当我们把把Multimap的概念和功能相结合的时候,你就会意识到他到底有多强大了,而不仅仅是过滤那么简单!
我们假设我们已经拥有了包含了一组map的list。list里的每一个Map代表拥有指定属性的一个文档。这个Map看起来可能会是下面这个样子:
1
|
mapOf( "type" , "blog" , "id" , "292" , "author" , "john" ); |
即每个Map中我们拥有3个属性,他们分别是“type”、 “id”和“author”。
如上所示,所有我们的List看起来应该是下面这个样子:
1
|
List<Map<String, |
现在,我们想把这个list根据所装载对象的类型不同分成多个list,比如一个叫“blog”,一个叫“news”等等…
如果没有Google Collections这将是一场恶梦!我们必须得先循环这个list,然后再分别检查每一个map中的key,然后再把根据类型的不同放入不同的list中。但如果我们不知道map里都有哪些类型,这个过程会更痛苦!
想不想和我一起来看看有没有轻松的办法解决?
用一点点Function的魔法加上Multimaps,我样可以以一种上相当优雅的方式来解决这个问题:
1
2
3
4
5
6
7
|
Multimap<String, listOfMaps, new
public
final
return
"type" ); } }); |
现在我们拥有了每一个key代表不同类型的Multimaps了!
如果现在我们想要指定类型的所有map,唯一需要做的就是找Multimaps要!
好,就到这里为止了!希望你喜欢这段旅程,同时也希望你能从Google这些真正伟大的项目中受到启发!
Guava 教程(4):条件,多重映射和分片的更多相关文章
- 使用Dapper处理多个结果集和多重映射的教程
在本文中,我们将介绍如何使用DAPPER从单个数据库调用中读取数据库中的多个结果集.我们将看看我们可能希望这样做的场景,以及如何使用它的Query和QueryMultiple方法更简洁地实现这一点. ...
- Guava 教程(3):Java 的函数式编程,通过 Google Collections 过滤和调用
原文出处: oschina 在本系列博客的第一.二部分,我介绍了非常优秀的Google Collections和Guava包.本篇博客中我们来看看如何使用Google Collections来做到过滤 ...
- Guava HashMultiMap(MultiMap)反转映射
(一)MultiMap 多重map,一个key可以对应多个值(多个值放在一个list中),可用于分组 举例: Multimap<String, Integer> map = HashMul ...
- 【guava】前提条件
guava为编写漂亮代码提供了很大的便利,今天,我想向你展示下我是怎么使用预判断来避免不必要的if/throw 申明,使用选择来提升代码逻辑性. 预判断并不是新东西,Apache Commons项目有 ...
- ABP进阶教程1 - 条件查询
点这里进入ABP进阶教程目录 添加实体 打开领域层(即JD.CRS.Core)的Entitys目录 //用以存放实体对象添加一个枚举StatusCode.cs //状态信息 using System; ...
- Linux makefile教程之条件判断六[转]
使用条件判断 —————— 使用条件判断,可以让make根据运行时的不同情况选择不同的执行分支.条件表达式可以是比较变量的值,或是比较变量和常量的值. 一.示例 下面的例子,判断$(CC)变量是否“g ...
- nhibernate教程(4)--条件查询(Criteria Query)
NHibernate之旅(4):探索查询之条件查询(Criteria Query) 2008-10-16 18:20 by 李永京, 44341 阅读, 43 评论, 收藏, 编辑 本节内容 NHi ...
- Guava 教程2-深入探索 Google Guava 库
原文出处: oschina 在这个系列的第一部分里,我简单的介绍了非常优秀的Google collections和Guava类库,并简要的解释了作为Java程序员,如果使用Guava库来减少项目中大量 ...
- Guava 教程1-使用 Google Collections,Guava,static imports 编写漂亮代码
原文出处: oschina (API:http://ifeve.com/category/framework/guava-2/ JAR DOC Source 链接:http://pan.baidu.c ...
随机推荐
- EF Core 2.0使用MsSql/Mysql实现DB First和Code First
参考地址 EF官网 ASP.NET Core MVC 和 EF Core - 教程系列 环境 Visual Studio 2017 最新版本的.NET Core 2.0 SDK 最新版本的 Windo ...
- 彻底理解Oracle中的集合操作与复合查询
--Oracle中的复合查询 复合查询:包含集合运算(操作)的查询 常见的集合操作有: union: 两个查询的并集(无重复行.按第一个查询的第一列升序排序) union all:两个查询的并集(有重 ...
- Window下使用ftp命令往Linux中发送文件
操作步骤:首先,切换到文件目录1.ftp ip地址2.连接成功后,输入正确的用户名和密码.3.binary(表示以二进制的格式传送)4.put/get 文件名(或文件的绝对路径) 退出:bye
- PHP MySQL 简介
PHP MySQL 简介 通过 PHP,您可以连接和操作数据库. MySQL 是跟 PHP 配套使用的最流行的开源数据库系统. 如果想学习更多 MySQL 知识可以查看本站MySQL 教程. MySQ ...
- GDAL C#中文路径,中文属性名称乱码问题
昨天写的博客,将C#读取shp中文属性值乱码的问题应该可以解决,博客地址为:http://blog.csdn.net/liminlu0314/article/details/54096119,然后又测 ...
- SpringBatch的核心组件JobLauncher和JobRepository
Spring Batch的框架包括启动批处理作业的组件和存储Job执行产生的元数据.因此只需掌握配置这个基础框架在批处理应用程序中即启动Jobs并存储Job元数据. 组件:Job Launcher和J ...
- Android广播的发送与接收
Android广播的发送与接收 效果图 广播发送 广播分为有序广播和无序广播 有序广播与无序广播的区别 无序广播:只要是广播接收者指定了接收的事件类型,就可以接收到发送出来的广播消息.不能修改消息. ...
- 网站开发进阶(四十四)input type="submit" 和"button"的区别
网站开发进阶(四十四)input type="submit" 和"button"的区别 在一个页面上画一个按钮,有四种办法: 这就是一个按钮.如果你不写ja ...
- java.util.Arrays类详解(源码总结)
概述 Arrays类位于java.util包下,是一个对数组操作的工具类.今天详细的看了看Arrays类的4千多行源码,现将Arrays类中的方法做一个总结(JDK版本:1.6.0_34).Array ...
- Java继承时的初始化顺序
Java程序在启动和运行时,需要首先完成初始化的工作.在涉及到继承.static成员变量等因素时,初始化的顺序就复杂起来.下面以一个例子说明继承时的Java初始化顺序. 例子: class Insec ...