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表达式是延迟执行的,这正好可以作为解决方案,提升性能 . 性能浪费的日志案例 注意:日志可以帮助 ...
随机推荐
- vue-cli搭建项目的目录结构及说明
vue-cli基于webpack搭建项目的目录结构 build文件夹 ├── build // 项目构建的(webpack)相关代码 │ ├── build.js ...
- Linux 查看CPU温度
安装 lm-sensors sudo apt-get install lm-sensors # 安装yes | sudo sensors-detect # 侦测所有感测器 sensors # 查看温度 ...
- C语言多维数组的指针传递
在C语言中为了节省空间,提高运行速度经常使用指针来完成数组的传递. 对于一维数组而言可以直接传递首地址 而对于二维数组必须在传递时声明是二维数组的指针,并且调用时也要经过一些运算 首先是定义形参: 函 ...
- Go 语言循环语句
在不少实际问题中有许多具有规律性的重复操作,因此在程序中就需要重复执行某些语句. 以下为大多编程语言循环程序的流程图: Go 语言提供了以下几种类型循环处理语句: 循环类型 描述 for 循环 重复执 ...
- ERROR: Cannot change version of project facet Dynamic Web Module to 3.0?
Issue: When you create web app in eclipse with maven configuration, you may get following error. Can ...
- Scikit-learn:分类classification
http://blog.csdn.net/pipisorry/article/details/53034340 支持向量机SVM分类 svm分类有多种不同的算法.SVM是非常流行的机器学习算法,主要用 ...
- OpenResty修改Nginx默认autoindex页面
Nginx的autoindex 命令可以自动列出目录下的文件,一些网站用这个功能做文件下载,但是Nginx又没有提供这个页面的 自定义的功能,后来看到别人提及 ngx_openresty,才想到 bo ...
- Android适配难题全面总结
支持多种屏幕 Android 可在各种具有不同屏幕尺寸和密度的设备上运行.对于 应用,Android 系统在不同设备中提供一致的开发环境, 可以处理大多数工作,将每个应用的用户界面调整为适应其显示的 ...
- 设子数组A[0:k]和A[k+1:N-1]已排好序(0≤K≤N-1)。试设计一个合并这2个子数组为排好序的数组A[0:N-1]的算法。
设子数组A[0:k]和A[k+1:N-1]已排好序(0≤K≤N-1).试设计一个合并这2个子数组为排好序的数组A[0:N-1]的算法.要求算法在最坏情况下所用的计算时间为O(N),只用到O(1)的辅助 ...
- 让sublime总是在新选项卡打开新文件
sublime的一个默认设置让人很不爽,比如现在选项卡里面已经打开了一个文件A,当你从左边side bar里面点击一个新文件B时,如果你不是快速的双击,且A没有处于编辑未保存状态,那么B就会覆盖A的选 ...