Eclipse Collections — это платформа Java Collections с открытым исходным кодом, которая позволяет писать функциональный, свободный код на Java.
история
Eclipse Collections начиналась как фреймворк коллекций под названием Caramel в Goldman Sachs в 2004 году. С тех пор фреймворк развивался, и в 2012 году он был открыт для GitHub в качестве проекта GS Collections. За эти годы около 40 или около того разработчиков из одной компании внесли свой вклад в структуру коллекций. Чтобы максимально использовать возможности проекта с открытым исходным кодом, GS Collections был перенесен в Eclipse Foundation, который в 2015 году был переименован в Eclipse Collections. Теперь эта структура полностью открыта для сообщества и принимает взносы!
Цели дизайна
Eclipse Collections была разработана для предоставления многофункционального, функционального, свободного и интересного API, а также структур данных с эффективным использованием памяти, обеспечивая при этом совместимость с коллекциями Java. Он предоставляет отсутствующие типы, такие как Bag
, Multimap
, Stack
, BiMap
, Interval
.
Эволюция рамок
За последние 14 с лишним лет фреймворк стал более RichIterable
обладает наивысшим интерфейсом: теперь в RichIterable
содержится более 100 методов. Эти методы были включены в интерфейс после тщательного обсуждения. Ниже приведены шаги, которые мы предпринимаем при добавлении API:
1. Вариант использования: большинство методов, добавленных в платформу, мотивируются требованиями пользователя. Пользователи будут поднимать либо проблему, либо напрямую запрос на извлечение проекта, а затем мы начинаем обсуждение.
2. Static Utility vs API: Eclipse Collections имеет статические служебные классы, такие как ListIterate
, ListIterate
и т. Д. Эти статические служебные классы позволяют нам ListIterate
прототипы наших функций перед добавлением их в качестве API. Если методы статической утилиты интенсивно используются, то в следующем выпуске мы попытаемся реализовать этот метод в виде API на интерфейсе коллекции, чтобы обеспечить богатый и свободный опыт кодирования.
Например: Iterate#groupByAndCollect()
в настоящее время реализован в статической утилите. Поскольку этот метод часто используется, он оправдывает добавление его в качестве API в RichIterable
чтобы обеспечить богатый, функциональный и свободный опыт кодирования. Существует открытая проблема, если вы хотите помочь нам.
3. Переопределения ковариантов. Мы логически переопределяем методы API, так что API возвращает тип, соответствующий его поведению.
Например: RichIterable
имеет API-интерфейс select()
который похож на filter()
который возвращает все элементы коллекций, которые оценивают значение true для Predicate
. Ниже описано, как API определяется на каждом интерфейсе:
1
2
3
4
5
6
7
8
|
// RichIterable RichIterable< T > select(Predicate<? super T> predicate); // ListIterable ListIterable< T > select(Predicate<? super T> predicate); // MutableList MutableList< T > select(Predicate<? super T> predicate) |
Как вы можете видеть, select()
на
— RichIterable
возвращает RichIterable
— ListIterable
возвращает ListIterable
MutableList
возвращает MutableList
4. Перегрузка с помощью Target. Иногда возможно, что нам нужна коллекция, отличная от возвращенной. Чтобы сделать его эффективным и быстрым, мы создаем перегруженный метод, который принимает целевую коллекцию. Целевые коллекции используются для накопления результатов и возврата целевой коллекции.
Например: как описано выше, метод select()
в MutableList
возвращает MutableList
. Тем не менее, что если вы хотите MutableSet
? Доступен перегруженный метод select()
который принимает целевую коллекцию, которая может быть набором.
1
2
3
4
5
6
7
8
9
|
MutableList<Integer> integers = Lists.mutable.with( 1 , 2 , 2 , 3 , 3 , 3 , 4 , 4 , 4 , 4 ); MutableList<Integer> evens = integers.select(each -> each % 2 == 0 ); Assert.assertEquals(Lists.mutable.with( 2 , 2 , 4 , 4 , 4 , 4 ), evens); MutableSet<Integer> uniqueEvens = integers.select( each -> each % 2 == 0 , Sets.mutable.empty()); Assert.assertEquals(Sets.mutable.with( 2 , 4 ), uniqueEvens); |
5. Симметрия: Eclipse Collections предлагает примитивные коллекции. Мы стараемся поддерживать симметрию между коллекциями объектов и примитивными коллекциями, чтобы обеспечить полное взаимодействие с пользователем.
Реализация API на практике
Давайте реализуем простой API RichIterable#countBy()
который был добавлен в выпуске Eclipse Collections 9.0.0: Мотивация для этого API была пользователями, которые упоминали о необходимости collect()
коллекцию в Bag
. В Eclipse Collections collect()
похож на map()
а Bag
— это структура данных, которая поддерживает отображение объекта на счетчик.
1
2
3
4
5
6
7
8
9
|
MutableList<String> strings = Lists.mutable.with( "1" , "2" , "2" , "3" , "3" , "3" , "4" , "4" , "4" , "4" ); Bag<Integer> integers = strings.collect( Integer::valueOf, Bags.mutable.empty()); Assert.assertEquals( 1 , integers.occurrencesOf( 1 )); Assert.assertEquals( 2 , integers.occurrencesOf( 2 )); Assert.assertEquals( 3 , integers.occurrencesOf( 3 )); Assert.assertEquals( 4 , integers.occurrencesOf( 4 )); |
Приведенное выше решение для подсчета целых чисел сработало, однако оно не было интуитивно понятным. Неопытному разработчику может быть трудно реализовать это решение. Итак, мы решили добавить countBy()
и теперь код выглядит более функциональным, плавным и, более того, интуитивно понятным.
1
2
3
4
5
6
7
|
MutableList<String> strings = Lists.mutable.with( "1" , "2" , "2" , "3" , "3" , "3" , "4" , "4" , "4" , "4" ); Bag<Integer> integers = strings.countBy(Integer::valueOf); Assert.assertEquals( 1 , integers.occurrencesOf( 1 )); Assert.assertEquals( 2 , integers.occurrencesOf( 2 )); Assert.assertEquals( 3 , integers.occurrencesOf( 3 )); Assert.assertEquals( 4 , integers.occurrencesOf( 4 )); |
Резюме
В этом блоге я объяснил стратегию развития зрелой библиотеки коллекций Java. Мы рассматриваем следующие аспекты: сценарий использования, утилита и API, ковариантные переопределения, необходимые перегрузки и, наконец, симметрия.
сноска
Это личная цель — получить 1000 звезд в нашем проекте GitHub , поэтому, если вам нравится среда, продемонстрируйте свою поддержку и поставьте звезду в хранилище.
Опубликовано на Java Code Geeks с разрешения Nikhil Navidadekar , партнер нашей программы JCG . Смотрите оригинальную статью здесь: API дизайн коллекций Eclipse Мнения, высказанные участниками Java Code Geeks, являются их собственными. |