歷史
Eclipse Collections於2004年在Goldman Sachs開始作爲一個名爲Caramel的集合框架開始。從那時起,該框架已經發展,並且在2012年,它作爲一個名爲GS Collections的項目開放給GitHub。多年來,大約40名來自同一公司的開發人員爲集合框架做出了貢獻。爲了最大限度地發揮開源項目的最佳性質,GS Collections被遷移到Eclipse Foundation,在2015年重新命名爲Eclipse Collections。現在,該框架對社區完全開放,接受貢獻!
設計目標
Eclipse Collections旨在提供豐富,功能,流暢,有趣的API以及內存高效的數據結構,同時提供與Java Collections的互操作性。它提供了缺失的類型,如Bag
,Multimap
,Stack
,BiMap
,Interval
。
框架的演變
在過去14年多的時間裏,該框架已經成熟並具有最高的界面:RichIterable
現在有超過100種方法。經過仔細考慮後,這些方法被包含在界面中。以下是我們在添加API時採取的步驟:
1.用例: 添加到框架中的大多數方法都是出於用戶需求。用戶將在項目中提出問題或直接提出請求,然後我們開始討論。
2.靜態實用程序與API: Eclipse集合具有靜態實用程序類,如Iterate
,ListIterate
等。這些靜態實用程序類允許我們在將其添加爲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 > 整數 = 列表。可變的。用(
1,2,2,3,3,3,4,4,4,4);
MutableList < 整數> 找齊 = 整數。選擇(每個 - > 每個 % 2 == 0);
斷言。的assertEquals(解釋。可變的。與(2,2,4,4,4,4),找齊);
MutableSet < Integer > uniqueEvens = 整數。選擇(
每個 - > 每個 % 2 == 0,
集。可變的。empty());
斷言。的assertEquals(集。可變。與(2,4),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,協變覆蓋,必要的重載,最後是對稱性。