Guava 教程(3):Java 的函数式编程,通过 Google Collections 过滤和调用
在本系列博客的第一、二部分,我介绍了非常优秀的Google Collections和Guava包。本篇博客中我们来看看如何使用Google Collections来做到过滤和排序功能。此外,我会带你看看Google Collections是如何使Java有一点点“functional(方法化)”的进步了。
Functions, Functions, Functions!!
Google Collections给我们带来了一对非常优雅的东东,叫做:Functions and Predicates! 和你使用的scala一样有神奇的地方,现在你可以使用在no-functional 的java身上了。你可以在com.google.common.base包里找到这些(更多)。
我们将在下一部分过滤集合的时候谈到Predicates类,首先我们先看一下Function的用法!
Google collections提供了Function<F,T>接口,实际上,一个function就是从一个对象到另外一个对象的转换变形。
像Lists和Maps这类的Collection工具类给我们提供了转换的方法:
|
1
2
|
topMaptoList |
举个例子来说,假设你有一个Map,key是物品,value是对应的价格,单位是欧元。那么,你有个需求是将里面的价格都转换为美元,传统的做法是遍历整个Map,然后更新每个value值,将价格转换为美元价格,好麻烦。。。
有了Functions,世界一下子变清净了…
|
1
2
3
4
5
6
|
Mapnew double1.4888; publicfinal return } }); |
好吧,你可能说匿名内部类搞的有点糟,因为 你可能想重用这个function—这里只是演示函数式的一些特点而已。
和这个类似的,我们也可以使用Functions来把一个对象转换成一个完全不同的对象,比如将一个整形转换为字符串。
我们稍后再深入Functions类,首先我们浏览一下Multimap集合以及我们如果使用一点function来转换一个集合。
使用条件过滤集合
我在Integrasco做数据工作时遇到的最常见的任务是过滤数据和对大集合进行排序。 简单起见,我们假设你有一个姓名列表想要过滤(看起来有点幼稚):
|
1
|
List<String>"Aleksander","Jaran","Integrasco","Guava","Java"); |
我们可以使用com.google.common.collect.Iterables和com.google.common.base.Predicates类来过滤例子中的列表,使过滤后的列表中只包含Aleksander或者Jaran:
现在我知道这听起来有点傻帽,但是你仍然可以实现自己的Predicates条件类,比如返回名字长度小于5的列表(我从codemonkeyism.com偷到了下面这个例子):
|
1
|
Iterable<String>"Aleksander"),equalTo("Jaran")),5))); |
这个例子返回的是Aleksander,Jaran以及Java(因为Java的长度小于5)。or条件的部分读起来有点绕,但我还可以忍受。equalTo以及or条件都是Predicates自带的方法,用起来很方便。
现在我们来实现一个lengthLessThan的条件,我们只需要这么做:
|
1
2
3
4
5
6
7
8
9
|
private implements private privatefinal this.length } public final return } } |
把这个实现在你的工具类里包装一下就像这样:
|
1
2
3
|
public final return } |
关注一下 Stephan的博文 fluent
interfaces for Google Collections –写的相当优雅~!
对集合排序
多亏有了java Collections类,我们可以这么排序:
|
1
|
Collections.sort(List<T>,super |
但有时候我们想做更复杂一些的事情,比如合并多个Comparator或者我们可能只是想要排序过的集合的一个视图,而不改变原来集合的顺序。
Google Collections给我们提供了Ordering,让我们更好地掌控排序。假如我们有两个对Person类排序的comparator,一个是根据lastName排序,一个是根据firstName排序:
|
1
2
3
4
5
|
Comparator<Person>new public finalfinal return }} |
Comparator<Person> byFirstName = new Comparator<Person>() {
public int compare(final Person p1, final Person p2) {
return p1.getFirstName().compareTo(p2.getFirstName());
}
};
那么,假如我们现在想现根据last name排序,再根据first name排序,然后对排序结果反序,那我们我们需要做的是:
List<Person> sortedCopy = Ordering.from(byLastName).compound(byFirstName).reverse().sortedCopy(persons);
而且,你甚至无需创建Comparator比较器,你可以直接扩展Ordering类!
|
1
|
List<Person> |
继续过滤和排序
在这个系列的第一部分,Steve提到了在Scala中,你可以这么做:
|
1
|
people.filter(_.firstName"Steve").sort(_.lastName |
功能是说从people这个集合中筛选出firstName为“Steve”的,并且按他们的lastName属性排序。
从语法上来看,这行代码非常优雅!那么我们也来看一下使用Google Collections时应该怎么做。Google Collections给我们提供了前面提到的Iterables类,我们可以使用Iterables类来实现过滤和转换(你可以使用Google Collections里的Collections2来实现同样的功能)。
那现在我们就来看一下如何实现和Steve的那行Scala代码一样的功能,虽然看起来没有Scala实现的那么优雅,但却是使用Predicates和Ordering类来实现上面功能的一种方式。
|
1
|
Ordering.from(byLastName).sortedCopy(filter(persons,"Steve"))); |
虽然跟Scala提供的语法糖有点差距(很明显我们还是需要我们的“withFirstName”条件谓词以及“byLastName”比较器),但至少这比我们不使用Google Collections接近多了!(如果采用Stephen的流式接口的话,代码会更易读)。
Kevin Bourrillion在另一篇关于使用Google
Collections编写函数式的Java的文章中提到:
语法很烂。而且同时这在语言本身改变之前只是权宜之计,到那时我们才真正的选择最佳的语法并开始真正的函数式编程。所以我还没决定我会投入多大的努力到Function/Predicate中去(这段真的很难翻译..我去..)
在下篇也是最后一篇关于Google Collections和Guava的博文中,我们将看到如果使用Google Collections操作Set和Map,以及使用Preconditiones来做验证,而且我们带你体验一下奇妙的Multimap集合类以及如何进行切分!
拭目以待吧!
Guava 教程(3):Java 的函数式编程,通过 Google Collections 过滤和调用的更多相关文章
- Guava 是个风火轮之函数式编程(3)——表处理
云栖社区> 博客列表> 正文 Guava 是个风火轮之函数式编程(3)--表处理 潘家邦 2016-01-26 13:19:21 浏览1062 评论0 java Guava 摘要: 早先学 ...
- paip. java的 函数式编程 大法
paip. java的 函数式编程 大法 Java 语言中常被忽视的一个方面是它被归类为一种命令式(imperative)编程语言.命令式编程虽然由于与 Java 语言的关联而相当普及,但是并不是惟一 ...
- Java 8 新特性-菜鸟教程 (3) -Java 8 函数式接口
Java 8 函数式接口 函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口. 函数式接口可以被隐式转换为lambda表达式. 函数式接 ...
- Java Stream函数式编程案例图文详解
导读 作者计划把Java Stream写成一个系列的文章,本文只是其中一节.更多内容期待您关注我的号! 一.什么是Java Stream? Java Stream函数式编程接口最初是在Java 8中引 ...
- Java Stream函数式编程图文详解(二):管道数据处理
一.Java Stream管道数据处理操作 在本号之前发布的文章<Java Stream函数式编程?用过都说好,案例图文详解送给你>中,笔者对Java Stream的介绍以及简单的使用方法 ...
- Java 8 函数式编程
今天打开Oracle Java官网一看,Java已经更新到 13 了 https://www.oracle.com/technetwork/java/javase/jdk-relnotes-index ...
- Scala学习教程笔记二之函数式编程、Object对象、伴生对象、继承、Trait、
1:Scala之函数式编程学习笔记: :Scala函数式编程学习: 1.1:Scala定义一个简单的类,包含field以及方法,创建类的对象,并且调用其方法: class User { private ...
- Scala学习教程笔记三之函数式编程、集合操作、模式匹配、类型参数、隐式转换、Actor、
1:Scala和Java的对比: 1.1:Scala中的函数是Java中完全没有的概念.因为Java是完全面向对象的编程语言,没有任何面向过程编程语言的特性,因此Java中的一等公民是类和对象,而且只 ...
- Java 之 函数式编程
一.Lambda 的延迟执行 有些场景的代码执行后,结果不一定会被使用,从而造成性能浪费.而Lambda表达式是延迟执行的,这正好可以作为解决方案,提升性能 . 性能浪费的日志案例 注意:日志可以帮助 ...
随机推荐
- Java不走弯路教程(前言)
本教程的程序基于Windows开发,所以你需要有一台安装Windows操作系统的电脑. 前言本教程将带你完成Java的初学和WEB框架的开发,学完本教程,你将完成对Java的入门并且对下一步不再迷茫. ...
- Win10 下Cmake编译配置 Opencv3.1 + Cuda7.5 + VS2013
折腾了三天终于配置成功了,在此写下编译配置的全部步骤和遇到的很多坑. 整体介绍: OpenCV 中 CUDA 实现的函数还不是太多,使用前要在OpenCV的官网上确认以下你想要的功能是否已经实现,否则 ...
- python中input()和raw_input()的区别
两者均是python的内置函数,通过读取控制台的输入与用户实现交互.raw_input:将所有输入作为字符串看待,不管用户输入什么类型的都会转变成字符串. raw的 ...
- 如何判断页面是qq浏览器还是微信浏览器打开
// 判断是QQ浏览器还是微信浏览器的js代码isWx = function() { var ua = navigator.userAgent.toLowerCase(); return ua.mat ...
- 剑指架构师系列-持续集成之Maven+Nexus+Jenkins+git+Spring boot
1.Nexus与Maven 先说一下这个Maven是什么呢?大家都知道,Java社区发展的非常强大,封装各种功能的Jar包满天飞,那么如何才能方便的引入我们项目,为我所用呢?答案就是Maven,只需要 ...
- C语言多维数组的指针传递
在C语言中为了节省空间,提高运行速度经常使用指针来完成数组的传递. 对于一维数组而言可以直接传递首地址 而对于二维数组必须在传递时声明是二维数组的指针,并且调用时也要经过一些运算 首先是定义形参: 函 ...
- Hibernate异常之关键字错误
三月 08, 2018 7:50:25 下午 org.hibernate.tool.schema.internal.ExceptionHandlerLoggedImpl handleException ...
- Android需求之点击跳转至市场评价
相信大家都看过APP上有一个选项"喜欢此APP?还希望您评价一下吧!",然后点击弹出选择框让你选择一个市场如: 安智市场,百度应用,豌豆荚-.然后选择其中一个后就跳转至此市场你的A ...
- Scikit-learn:分类classification
http://blog.csdn.net/pipisorry/article/details/53034340 支持向量机SVM分类 svm分类有多种不同的算法.SVM是非常流行的机器学习算法,主要用 ...
- uboot-tiny4412启动流程(下)----如何将自己的裸板测试程序加入uboot中启动测试
今天在工作上搞了一天高通的芯片uboot程序,目的是希望将一个裸板的程序移植到uboot中,并且开机让它运行.这个芯片是NXP4330,目前是高通的一个芯片,基于ARM-contexA9架构,那么就跟 ...