设为首页 加入收藏

TOP

Eclipse Collections随Java版本的演变(一)
2017-10-30 06:07:07 】 浏览:427
Tags:Eclipse Collections Java 版本 演变

Eclipse Collections是Java Collections框架的替代者。它提供JDK兼容的List、Set和Map实现,并且提供了丰富的API以及JDK中没有的其他类型,如Bags、Multimaps和BiMaps。Eclipse Collections还充分补充了原始容器。在2012年开源之前,该框架在Goldman Sachs内部已经开发了10年,那时称为GS Collections。2015年,它被迁移到Eclipse基金会。从那会开始,所有开发都是在Eclipse Collections名下完成的。如果你想阅读一些优质的介绍性文章,可以看下Donald Raab发表在InfoQ上的文章“GS Collections实例教程”第一部分第二部分


在讨论任何细节或代码示例之前,让我们了解下本文的代码片段来自什么领域,如下图所示:


我们有一个人的列表(类型为Person),每个人对应一个Pet列表,每只宠物都是枚举类型PetType中的一种。


在Eclipse Collections 8发布之前,EC兼容的Java版本为5和7之间的版本。开发人员也可以使用Java 8,既使用框架提供的丰富API,同时又充分利用Lambda表达式和方法引用的优势,而实际效果还不错。


但你能做的也就只有那些。Eclipse Collections与Java 8兼容,但它没有使用或包含Java 8。现在,从Eclipse Collections 8开始,我们已经决定兼容Java 8及以上版本,从而可以开始在我们的代码库中利用部分绝妙的Java 8新特性。


Optional是Java 8中最受欢迎的新特性之一。据Javadoc介绍,“一个容器对象可能包含也可能不包含非空值。如果值存在,那么isPresent()会返回true,而get()会返回那个值”。从根本上讲,Optional强制开发人员处理潜在的null项,帮助他们避免NullPointerExceptions。那么,我们可以在Eclipse Collections的那个地方使用这项特性呢?RichIterable.detectWith()非常适合。detectWith接收一个Predicate参数,返回集合中满足那个条件的第一个元素。如果它没有找到任何元素,则返回null。因而,在8.0版本中,我们引入了detectWithOptional()。该方法不会返回一个元素或null,它返回一个Optional对象,然后由用户来处理,参见下面的代码(来自我们的kata教程资料):


在这段代码中,我们想查找Mary Smith。当调用detectWith方法时,person对象被置为null,因为它没有找到任何满足条件的人。因此,这段代码会抛出NullPointerException。


接下来,在Java 8之前,我们可以总是使用上面这样的null检查。但是,Java 8提供了Optional,那么我们就用它吧!


在这段代码中,detectWithOptional没有返回null,而是返回了一个封装了Person的Optional。现在,由开发人员决定如果处理这种潜在的null值。在我的代码中,如果它不是null,我就调用orElseGet()新建一个Person实例。测试通过,我们避免了任何异常!


如果你的代码中使用了Streams,那么你之前很可能使用过Collector。Collector是一种实现可变归约操作的方法。例如,Collectors.toList()让开发人员可以将Stream中的数据项累加到列表中。JDK有多个“内置”的Collector,可以从Collectors类里找到。下面是一些Java 8(不是Eclipse Collections)的例子:


既然现在我们可以在使用Eclipse Collections时利用Streams,我们也应该内建自己的Collectors——Collectors2。其中许多Collector都是针对特定的Eclipse Collections数据结构的,有些特性是JDK没有直接提供的,如toBag()、toImmutableSet()等。


(点击查看大图)


上图简要介绍了Collectors2 API。上面的方框是所有可以存储Collectors2结果的不同数据结构,下面各项是部分可以达到这个目的API。可以看到,Collectors2既支持JDK和Eclipse Collections的类型,也支持原始集合。开发人员甚至可以通过Collectors2使用他们熟悉的collect()、select()、reject()等API。


Collectors和Collectors2之间也可以交互;二者并不相互排斥。看下下面这个例子,我们使用了JDK 8 Collectors,但方便起见,我们接着使用了EC 8.0 Collectors2:


上面两段代码的输出完全一种,但实现上有细微的差别:Eclipse Collections提供了makeString()功能,它创建了一个逗号分隔的元素集合,并表示为一个字符串。使用Java 8做到这一点,就需要多做一点工作,调用Collectors.mapping(),将每个对象转换成toString值,然后使用逗号连接在一起。


对于像Eclipse Collections这样的框架,默认方法是对JDK的一个很好的补充。我们可以在部分最上层的接口之上实现新API,而不必修改许多底层的实现。reduceInPlace()是我们向RichIterable添加的其中一个新方法——他有什么功能?


reduceInPlace和在Stream上使用Collector的效果完全一样。但是我们为什么要在Eclipse Collections中加入这个方法呢?原因非常有趣;在涉及Eclipse Collections提供的Immutable或Lazy API时,我们就不必再使用streaming API了。在这一点上,我们无法使用Collectors获得同样的功能,因为我们已经无法使用stream(),也无法调用后续的API;这就该reduceInPlace发挥作用了。


如下图所示,一旦我们调用了集合的.toImmutable()或.asLazy()方法,我们就无法再调用.stream()了。因此,如果我们想使用Collectors,那么我们现在可以使用.reduceInPlace()实现同样的效果。



从GS Collections 3.0开始,我们就受益于原始集合。Eclipse Collections优化了所有原始类型集合的内存,提供了和Object类型类似的接口,并且和原始类型相对应。


(点击查看大图)



从上图可以看出,使用原始集合有若干好处。开发人员可以不用装箱非原始类型,节省大量的内存。从Java 8开始,我们有三种原始类型(int、long和double),使用专用的原始流和Lambda表达式。在Eclipse Collections中,如果你希望使用同样的惰性求值,那么我们在八种原始类型上都直接提供了API。让我们看一下代码示例。


在上述代码中,我们创建IntStream 1、2、3,并试图调用它的min()和max()的方法。Java 8的Streams和迭代器类似,不允许重用。Eclipse Co

首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇在 React 中什么时候使用箭头函数 下一篇JavaScript 函数式编程介绍

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目