2KB项目,专业的源码交易网站 帮助 收藏 每日签到

Guava 教程3-Java 的函数式编程,通过 Google Collections 过滤和调用

  • 时间:2019-01-23 18:50 编辑:2KB 来源:2KB.COM 阅读:427
  • 扫一扫,手机访问
  • 分享
摘要:
Guava Google Collections 英文原文:Guava Lesson Part3-Functional Java, Filtering and Ordering with 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工具类给我们提供了转换的方法:

topMap = Maps.transformValues(fromMap, function);
toList = Lists.transform(fromList, function);
举个例子来说,假设你有一个Map,key是物品,value是对应的价格,单位是欧元。那么,你有个需求是将里面的价格都转换为美元,传统的做法是遍历整个Map,然后更新每个value值,将价格转换为美元价格,好麻烦。。。

有了Functions,世界一下子变清净了...

Map usdPriceMap = Maps.transformValues(eurPriceMap, new Function() {
            double eurToUsd = 1.4888;
            public Double apply(final Double from) {
                return from * eurToUsd;
            }
        });

好吧,你可能说匿名内部类搞的有点糟,因为 你可能想重用这个function---这里只是演示函数式的一些特点而已。

和这个类似的,我们也可以使用Functions来把一个对象转换成一个完全不同的对象,比如将一个整形转换为字符串。

我们稍后再深入Functions类,首先我们浏览一下Multimap集合以及我们如果使用一点function来转换一个集合。

使用条件过滤集合

我在Integrasco做数据工作时遇到的最常见的任务是过滤数据和对大集合进行排序。 简单起见,我们假设你有一个姓名列表想要过滤(看起来有点幼稚):

List<String> names = listOf("Aleksander", "Jaran", "Integrasco", "Guava", "Java");

我们可以使用com.google.common.collect.Iterables和com.google.common.base.Predicates类来过滤例子中的列表,使过滤后的列表中只包含Aleksander或者Jaran:

现在我知道这听起来有点傻帽,但是你仍然可以实现自己的Predicates条件类,比如返回名字长度小于5的列表(我从codemonkeyism.com偷到了下面这个例子):

Iterable<String> filtered = filter(names, or(or(equalTo("Aleksander"),equalTo("Jaran")), lengthLessThan(5)));

这个例子返回的是Aleksander,Jaran以及Java(因为Java的长度小于5)。or条件的部分读起来有点绕,但我还可以忍受。equalTo以及or条件都是Predicates自带的方法,用起来很方便。

现在我们来实现一个lengthLessThan的条件,我们只需要这么做:

private static class LengthLessThanPredicate implements Predicate<String> {
        private final int length;
        private LengthLessThanPredicate(final int length) {
            this.length = length;
        }
        public boolean apply(final String s) {
            return s.length() < length;
        }
    }
把这个实现在你的工具类里包装一下就像这样:
public static Predicate<String> lengthLessThan(final int length) {
        return new LengthLessThanPredicate(length);
    }
关注一下 Stephan的博文   fluent interfaces for Google Collections --写的相当优雅~!

对集合排序

多亏有了java Collections类,我们可以这么排序:

Collections.sort(List<T>, Comparator<? super T>)

但有时候我们想做更复杂一些的事情,比如合并多个Comparator或者我们可能只是想要排序过的集合的一个视图,而不改变原来集合的顺序。

Google Collections给我们提供了Ordering,让我们更好地掌控排序。假如我们有两个对Person类排序的comparator,一个是根据lastName排序,一个是根据firstName排序:

Comparator<Person> byLastName = new Comparator<Person>() {
    public int compare(final Person p1, final Person p2) {
        return p1.getLastName().compareTo(p2.getLastName());
    }
}
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类!
List<Person> sortedCopy = orderByLastName.compound(orderByFirstName).reverse().sortedCopy(persons);

继续过滤和排序

在这个系列的第一部分,Steve提到了在Scala中,你可以这么做:

people.filter(_.firstName == "Steve").sort(_.lastName < _.lastName) 
功能是说从people这个集合中筛选出firstName为“Steve”的,并且按他们的lastName属性排序。

从语法上来看,这行代码非常优雅!那么我们也来看一下使用Google Collections时应该怎么做。Google Collections给我们提供了前面提到的Iterables类,我们可以使用Iterables类来实现过滤和转换(你可以使用Google Collections里的Collections2来实现同样的功能)。

那现在我们就来看一下如何实现和Steve的那行Scala代码一样的功能,虽然看起来没有Scala实现的那么优雅,但却是使用Predicates和Ordering类来实现上面功能的一种方式。

Ordering.from(byLastName).sortedCopy(filter(persons, withFirstName("Steve")));
虽然跟Scala提供的语法糖有点差距(很明显我们还是需要我们的“withFirstName”条件谓词以及“byLastName”比较器),但至少这比我们不使用Google Collections接近多了!(如果采用Stephen的流式接口的话,代码会更易读)。

Kevin Bourrillion在另一篇关于使用Google Collections编写函数式的Java的文章中提到:

语法很烂。而且同时这在语言本身改变之前只是权宜之计,到那时我们才真正的选择最佳的语法并开始真正的函数式编程。所以我还没决定我会投入多大的努力到Function/Predicate中去(这段真的很难翻译..我去..)

在下篇也是最后一篇关于Google Collections和Guava的博文中,我们将看到如果使用Google Collections操作Set和Map,以及使用Preconditiones来做验证,而且我们带你体验一下奇妙的Multimap集合类以及如何进行切分!

拭目以待吧!

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部