Введение в коллекции Eclipse
1. обзор
Eclipse Collections - еще одна улучшенная среда сбора данных для Java.
Проще говоря, он предоставляет оптимизированные реализации, а также некоторые дополнительные структуры данных и функции, которых нет в ядре Java.
Библиотека предоставляет как изменчивые, так и неизменные реализации всех структур данных.
2. Maven Dependency
Начнем с добавления следующей зависимости Maven к нашемуpom.xml:
org.eclipse.collections
eclipse-collections
8.2.0
Последнюю версию библиотеки можно найти в папкеMaven Central Repository.
3. Большая картина
3.1. Основные типы коллекций
Основные типы коллекций в коллекциях Eclipse:
-
ListIterable - упорядоченная коллекция, которая поддерживает порядок вставки и допускает дублирование элементов. Подинтерфейсы включают:MutableList,FixedSizeList иImmutableList. Самый распространенныйListIterable implementation is FastList, which is a subclass of MutableList
-
SetIterable - коллекция, не допускающая повторяющихся элементов. Это может быть отсортировано или не отсортировано. Подинтерфейсы включают:SortedSetIterable иUnsortedSetIterable.. Самая распространенная несортированная реализацияSetIterable -UnifiedSet
-
MapIterable - набор пар ключ / значение. Подинтерфейсы включаютMutableMap,FixedSizeMap иImmutableMap. Двумя распространенными реализациями являютсяUnifiedMap иMutableSortedMap. В то время какUnifiedMap не поддерживает какой-либо порядок,MutableSortedMap поддерживает естественный порядок элементов
-
BiMap - набор пар ключ / значение, которые можно повторять в любом направлении. BiMap расширяет интерфейсMapIterable
-
Bag - неупорядоченная коллекция, допускающая дубликаты. Подинтерфейсы включаютMutableBag andFixedSizeBag. Наиболее распространенная реализация -HashBag
-
StackIterable - коллекция, которая поддерживает порядок «последний вошел, первый ушел», перебирая элементы в обратном порядке вставки. Подинтерфейсы включаютMutableStack иImmutableStack
-
MultiMap - набор пар ключ / значение, допускающий несколько значений для каждого ключа
3.2. Примитивные коллекции
The framework also provides a huge set of primitive collections; их реализации названы в соответствии с их типом. Существуют изменяемые, неизменяемые, синхронизированные и неизменяемые формы для каждого их типа:
-
ПримитивLists
-
ПримитивSets
-
ПримитивStacks
-
ПримитивBags
-
ПримитивMaps
-
IntInterval
Существует огромное количество примитивных форм карт, охватывающих все возможные комбинации примитивных или объектных ключей и примитивных или объектных значений.
Небольшое примечание -IntInterval - это диапазон целых чисел, который можно повторять, используя значение шага.
4. Создание коллекции
Чтобы добавить элементы вArrayList илиHashSet, мы создаем экземпляр коллекции, вызывая конструктор no-arg, а затем добавляя каждый элемент один за другим.
Хотя мы все еще можем сделать это в коллекциях Eclipse,we can also instantiate a collection and provide all initial elements at the same time in a single line.
Давайте посмотрим, как мы можем создать экземплярFastList:
MutableList list = FastList.newListWith(
"Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");
Точно так же мы можем создать экземплярUnifiedSet и добавить к нему элементы, передав элементы статическому методуnewSetWith():
Set comparison = UnifiedSet.newSetWith(
"Porsche", "Volkswagen", "Toyota", "Mercedes");
Вот как мы можем создатьHashBag:
MutableBag bag = HashBag.newBagWith(
"Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");
Создание карт и добавление к ним пар «ключ-значение» аналогично. Единственное отличие состоит в том, что мы передаем пары ключ и значение методуnewMapWith() как реализации интерфейсаPair.
Возьмем для примераUnifiedMap:
Pair pair1 = Tuples.pair(1, "One");
Pair pair2 = Tuples.pair(2, "Two");
Pair pair3 = Tuples.pair(3, "Three");
UnifiedMap map = new UnifiedMap<>(pair1, pair2, pair3);
Мы все еще можем использовать подход Java Collections API:
UnifiedMap map = new UnifiedMap<>();
map.put(1, "one");
map.put(2, "two");
map.put(3, "three");
Посколькуimmutable collections cannot be modified, they do not have implementations of methods that modify collections, напримерadd() иremove().
Неизменяемые коллекции, однако, позволяют нам вызывать эти методы, но в этом случае выдадутUnsupportedOperationException.
5. Получение элементов из коллекций
Так же, как при использовании стандартногоLists, элементы Eclipse CollectionsLists могут быть получены по их индексу:
list.get(0);
И значения карт Eclipse Collections можно получить с помощью их ключа:
map.get(0);
МетодыgetFirst() иgetLast() могут использоваться для получения первого и последнего элементов списка соответственно. В случае других коллекций они возвращают первый и последний элемент, который будет возвращен итератором.
map.getFirst();
map.getLast();
Методыmax() иmin() могут использоваться для получения максимального и минимального значений коллекции на основе естественного порядка.
map.max();
map.min();
6. Итерация по коллекции
Eclipse Collections предоставляет много способов перебора коллекций. Давайте посмотрим, что они из себя представляют и как работают на практике.
6.1. Коллекция Фильтрация
Шаблон выбора возвращает новую коллекцию, содержащую элементы коллекции, которые удовлетворяют логическому условию. По сути, это операция фильтрации.
Вот пример:
@Test
public void givenListwhenSelect_thenCorrect() {
MutableList greaterThanThirty = list
.select(Predicates.greaterThan(30))
.sortThis();
Assertions.assertThat(greaterThanThirty)
.containsExactly(31, 38, 41);
}
То же самое можно сделать с помощью простого лямбда-выражения:
return list.select(i -> i > 30)
.sortThis();
Шаблон отклонения является противоположным. Он возвращает коллекцию всех элементов, которые не удовлетворяют логическому условию.
Давайте посмотрим на пример:
@Test
public void whenReject_thenCorrect() {
MutableList notGreaterThanThirty = list
.reject(Predicates.greaterThan(30))
.sortThis();
Assertions.assertThat(notGreaterThanThirty)
.containsExactlyElementsOf(this.expectedList);
}
Здесь мы отклоняем все элементы, которые больше 30.
6.2. Методcollect()
Методcollect возвращает новую коллекцию, элементы которой являются результатами, возвращаемыми предоставленным лямбда-выражением - по сути, это комбинацияmap() иcollect() из Stream API.
Давайте посмотрим на это в действии:
@Test
public void whenCollect_thenCorrect() {
Student student1 = new Student("John", "Hopkins");
Student student2 = new Student("George", "Adams");
MutableList students = FastList
.newListWith(student1, student2);
MutableList lastNames = students
.collect(Student::getLastName);
Assertions.assertThat(lastNames)
.containsExactly("Hopkins", "Adams");
}
Созданная коллекцияlastNames содержит фамилии, которые собраны из спискаstudents.
Но,what if the returned collection is a collection of collections and we do not want to maintain a nested structure?
Например, если у каждого студента есть несколько адресов, и нам нужна коллекция, содержащая адреса в видеStrings, а не набор коллекций, мы можем использовать методflatCollect().
Вот пример:
@Test
public void whenFlatCollect_thenCorrect() {
MutableList addresses = students
.flatCollect(Student::getAddresses);
Assertions.assertThat(addresses)
.containsExactlyElementsOf(this.expectedAddresses);
}
6.3. Обнаружение элемента
Методdetect находит и возвращает первый элемент, удовлетворяющий логическому условию.
Давайте быстро рассмотрим пример:
@Test
public void whenDetect_thenCorrect() {
Integer result = list.detect(Predicates.greaterThan(30));
Assertions.assertThat(result)
.isEqualTo(41);
}
МетодanySatisfy определяет, удовлетворяет ли какой-либо элемент коллекции логическому условию.
Вот пример:
@Test
public void whenAnySatisfiesCondition_thenCorrect() {
boolean result = list.anySatisfy(Predicates.greaterThan(30));
assertTrue(result);
}
Точно так же методallSatisfy определяет, все ли элементы коллекции удовлетворяют логическому условию.
Давайте посмотрим на быстрый пример:
@Test
public void whenAnySatisfiesCondition_thenCorrect() {
boolean result = list.allSatisfy(Predicates.greaterThan(0));
assertTrue(result);
}
6.4. Методpartition()
Методpartition распределяет каждый элемент коллекции в одну из двух коллекций в зависимости от того, удовлетворяет ли элемент логическому условию.
Давайте посмотрим на пример:
@Test
public void whenAnySatisfiesCondition_thenCorrect() {
MutableList numbers = list;
PartitionMutableList partitionedFolks = numbers
.partition(i -> i > 30);
MutableList greaterThanThirty = partitionedFolks
.getSelected()
.sortThis();
MutableList smallerThanThirty = partitionedFolks
.getRejected()
.sortThis();
Assertions.assertThat(smallerThanThirty)
.containsExactly(1, 5, 8, 17, 23);
Assertions.assertThat(greaterThanThirty)
.containsExactly(31, 38, 41);
}
6.5. Ленивая итерация
Ленивая итерация - это шаблон оптимизации, в котором вызывается метод итерации, но его фактическое выполнение откладывается до тех пор, пока другой последующий метод не потребует его действия или возвращаемых значений.
@Test
public void whenLazyIteration_thenCorrect() {
Student student1 = new Student("John", "Hopkins");
Student student2 = new Student("George", "Adams");
Student student3 = new Student("Jennifer", "Rodriguez");
MutableList students = Lists.mutable
.with(student1, student2, student3);
LazyIterable lazyStudents = students.asLazy();
LazyIterable lastNames = lazyStudents
.collect(Student::getLastName);
Assertions.assertThat(lastNames)
.containsAll(Lists.mutable.with("Hopkins", "Adams", "Rodriguez"));
}
Здесь объектlazyStudents не получает элементы спискаstudents, пока не будет вызван методcollect().
7. Сопряжение элементов коллекции
Методzip() возвращает новую коллекцию, объединяя элементы двух коллекций в пары. Если какая-либо из двух коллекций длиннее, остальные элементы будут усечены.
Давайте посмотрим, как мы можем это использовать:
@Test
public void whenZip_thenCorrect() {
MutableList numbers = Lists.mutable
.with("1", "2", "3", "Ignored");
MutableList cars = Lists.mutable
.with("Porsche", "Volvo", "Toyota");
MutableList> pairs = numbers.zip(cars);
Assertions.assertThat(pairs)
.containsExactlyElementsOf(this.expectedPairs);
}
Мы также можем связать элементы коллекции с их индексами, используя методzipWithIndex():
@Test
public void whenZip_thenCorrect() {
MutableList cars = FastList
.newListWith("Porsche", "Volvo", "Toyota");
MutableList> pairs = cars.zipWithIndex();
Assertions.assertThat(pairs)
.containsExactlyElementsOf(this.expectedPairs);
}
8. Преобразование коллекций
Eclipse Collections предоставляет простые методы для преобразования типа контейнера в другой. Это методыtoList(),toSet(),toBag() иtoMap().
Давайте посмотрим, как мы можем их использовать:
public static List convertToList() {
UnifiedSet cars = new UnifiedSet<>();
cars.add("Toyota");
cars.add("Mercedes");
cars.add("Volkswagen");
return cars.toList();
}
Давайте запустим наш тест:
@Test
public void whenConvertContainerToAnother_thenCorrect() {
MutableList cars = (MutableList) ConvertContainerToAnother
.convertToList();
Assertions.assertThat(cars)
.containsExactlyElementsOf(
FastList.newListWith("Volkswagen", "Toyota", "Mercedes"));
}
9. Заключение
В этом руководстве мы рассмотрели краткий обзор коллекций Eclipse и функций, которые они предоставляют.
Полная реализация этого руководства доступнаover on GitHub.