JVM Advent Calendar:Eclipse集合的API设计

历史

Eclipse Collections于2004年在Goldman Sachs开始作为一个名为Caramel的集合框架开始。从那时起,该框架已经发展,并且在2012年,它作为一个名为GS Collections的项目开放给GitHub。多年来,大约40名来自同一公司的开发人员为集合框架做出了贡献。为了最大限度地发挥开源项目的最佳性质,GS Collections被迁移到Eclipse Foundation,在2015年重新命名为Eclipse Collections。现在,该框架对社区完全开放,接受贡献!

设计目标

Eclipse Collections旨在提供丰富,功能,流畅,有趣的API以及内存高效的数据结构,同时提供与Java Collections的互操作性。它提供了缺失的类型,如BagMultimapStackBiMapInterval

框架的演变

在过去14年多的时间里,该框架已经成熟并具有最高的界面:RichIterable现在有超过100种方法。经过仔细考虑后,这些方法被包含在界面中。以下是我们在添加API时采取的步骤:

1.用例:  添加到框架中的大多数方法都是出于用户需求。用户将在项目中提出问题或直接提出请求,然后我们开始讨论。

2.静态实用程序与API: Eclipse集合具有静态实用程序类,如IterateListIterate等。这些静态实用程序类允许我们在将其添加为API之前对我们的功能进行原型设计。如果大量使用静态实用程序方法,那么在后续版本中,我们尝试将该方法实现为集合接口上的API,以提供丰富而流畅的编码体验。

例如,  Iterate#groupByAndCollect()目前在静态实用程序上实现。由于该方法经常使用,因此可以将其作为API添加,RichIterable以提供丰富,功能和流畅的编码体验。如果您想帮助我们,有一个未解决的问题

3.协变覆盖:我们在逻辑上覆盖API方法,以便API返回一个类型,这对于它的行为是正确的。

例如,  RichIterable有一个名为的API select(),它类似于filter()并返回集合的所有元素,它们的值为true Predicate。以下是在每个界面上定义API的方式:

// RichIterable
RichIterable < T >  select(谓词<? super  T >  谓词);
 
// ListIterable
ListIterable < T >  select(谓词<? super  T >  谓词);
 
// MutableList
MutableList < T >  select(谓词<? super  T >  谓词)

 

如你所见,  select()on 
RichIterable返回a RichIterable
ListIterable返回a ListIterable
MutableList返回aMutableList

4.使用Target重载:有时,我们可能需要与返回的集合不同的集合。为了使其高效和流畅,我们创建了一个重载方法,它接受目标集合。目标集合用于累积结果并返回目标集合。

例如,如上所述,a上的select()方法MutableList返回a MutableList。但是,如果你想要一个MutableSet怎么办?有一个select()可用的重载方法,它接收可以是一个集合的目标集合。

MutableList < Integer >  整数 =  列表。可变的。用(
        1223334444);
MutableList < 整数>  找齐 =  整数。选择(每个 - >  每个 % 2  ==  0);
断言。的assertEquals(解释。可变的。与(224444),找齐);
 
MutableSet < Integer >  uniqueEvens  =  整数。选择(
        每个 - >  每个 % 2  ==  0
        集。可变的。empty());
断言。的assertEquals(集。可变。与(24),uniqueEvens);


5.对称性: Eclipse Collections提供原始集合。我们尝试保持对象集合和原始集合之间的对称性,以提供完整的用户体验。

在实践中实施API

让我们实现一个简单的API RichIterable#countBy(),它在Eclipse Collections版本9.0.0中添加:这个API的动机是用户提到必须在collect()一个集合中Bag。在Eclipse Collections中,  collect()类似于map(),并且Bag是一个维护对象到计数的映射的数据结构。

MutableList < String >  strings  =  Lists。可变的。用(
        “1”“2”“2”“3”“3”“3”“4”“4”“4”“4”);
Bag < Integer >  整数 =  字符串。收集(
        Integer :: valueOf,
        包包。可变的。empty());
断言。的assertEquals(1,整数。occurrencesOf(1));
断言。的assertEquals(2,整数。occurrencesOf(2));
断言。的assertEquals(3,整数。occurrencesOf(3));
断言。的assertEquals(4,整数。occurrencesOf(4));

 

以上计算整数的解决方案有效; 但是,它并不直观。没有经验的开发人员可能很难实现此解决方案。因此,我们决定添加countBy(),现在,代码看起来更实用,更流畅,更直观。

MutableList < String >  strings  =  Lists。可变的。用(
        “1”“2”“2”“3”“3”“3”“4”“4”“4”“4”);
Bag < Integer >  整数 =  字符串。countBy(Integer :: valueOf);
断言。的assertEquals(1,整数。occurrencesOf(1));
断言。的assertEquals(2,整数。occurrencesOf(2));
断言。的assertEquals(3,整数。occurrencesOf(3));
断言。的assertEquals(4,整数。occurrencesOf(4));

 

摘要

在这篇博客中,我解释了成熟Java集合库的演化策略。我们看到的方面是用例,实用程序与API,协变覆盖,必要的重载,最后是对称性。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值