1. Обзор
Eclipse Collections – это еще один улучшенный фреймворк коллекций для Java.
Проще говоря, он обеспечивает оптимизированные реализации, а также некоторые дополнительные структуры данных и функции, которых нет в ядре Java.
Библиотека предоставляет как изменяемые, так и неизменяемые реализации всех структур данных.
2. Зависимость Maven
Давайте начнем с добавления следующей зависимости Maven в ваш pom.xml :
org.eclipse.collections eclipse-collections 8.2.0
Мы можем найти последнюю версию библиотеки в Центральном репозитории Maven .
3. Общая Картина
3.1. Основные Типы Коллекций
Основными типами коллекций в коллекциях Eclipse являются:
- Listerable – упорядоченная коллекция, которая поддерживает порядок вставки и позволяет дублировать элементы. Подинтерфейсы включают: MutableList , Список фиксированного размера и ImmutableList . Наиболее распространенной итерационной реализацией List является Fast List, который является подклассом MutableList
- SetIterable – коллекция, которая не допускает дублирования элементов. Он может быть отсортирован или несортирован. Подинтерфейсы включают в себя: Сортируемый набор, повторяемый и Несортируемый. Наиболее распространенной несортированной Итерационной реализацией является Унифицированный набор
- MapIterable – набор пар ключ/значение. Подинтерфейсы включают Изменяемую карту , Фиксированную карту и неизменяемую карту . Двумя распространенными реализациями являются Unified Map и MutableSortedMap . В то время как UnifiedMap не поддерживает никакого порядка, MutableSortedMap поддерживает естественный порядок элементов
- BiMap – набор пар ключ/значение, которые можно перебирать в любом направлении. Растровое изображение расширяет интерфейс Map Iterable
- Сумка – неупорядоченная коллекция, которая допускает дубликаты. Подинтерфейсы включают MutableBag и |/Мешок фиксированного размера . Наиболее распространенной реализацией является Хэштег StackIterable
- – коллекция, которая поддерживает порядок “последний вход, первый выход”, повторяя элементы в обратном порядке вставки. Подинтерфейсы включают Изменяемый стек и Неизменяемый стек MultiMap
- – набор пар ключ/значение, который допускает несколько значений для каждого ключа
3.2. Примитивные коллекции
Фреймворк также предоставляет огромный набор примитивных коллекций ; их реализации названы в честь типа, который они содержат. Для каждого типа из них существуют изменяемые, неизменяемые, синхронизированные и неизменяемые формы:
- Примитивные Списки
- Примитивные Наборы
- Примитив Стеки
- Примитивные Сумки
- Примитив Карты
- Интервал
Существует огромное количество примитивных форм карт, охватывающих все возможные комбинации ключей примитива или объекта и значений примитива или объекта.
Краткое примечание – IntInterval – это диапазон целых чисел, которые могут быть повторены с использованием значения шага.
4. Создание экземпляра коллекции
Чтобы добавить элементы в ArrayList или HashSet , мы создаем экземпляр коллекции, вызывая конструктор no-arg, а затем добавляем каждый элемент по одному.
Хотя мы все еще можем сделать это в коллекциях Eclipse, мы также можем создать экземпляр коллекции и предоставить все начальные элементы одновременно в одной строке.
Давайте посмотрим, как мы можем создать экземпляр Быстрого списка :
MutableListlist = FastList.newListWith( "Porsche", "Volkswagen", "Toyota", "Mercedes", "Toyota");
Аналогично, мы можем создать экземпляр Унифицированного набора и добавить в него элементы, передав элементы в новый набор с помощью() статического метода:
Setcomparison = UnifiedSet.newSetWith( "Porsche", "Volkswagen", "Toyota", "Mercedes");
Вот как мы можем создать экземпляр хэштега :
MutableBagbag = HashBag.newBagWith( "Porsche", "Volkswagen", "Toyota", "Porsche", "Mercedes");
Создание экземпляров карт и добавление к ним пар ключей и значений аналогично. Единственное различие заключается в том, что мы передаем пары ключей и значений в новую карту с помощью метода() в качестве реализаций интерфейса Pair .
Возьмем в качестве примера Унифицированную карту :
Pairpair1 = Tuples.pair(1, "One"); Pair pair2 = Tuples.pair(2, "Two"); Pair pair3 = Tuples.pair(3, "Three"); UnifiedMap map = new UnifiedMap<>(pair1, pair2, pair3);
Мы все еще можем использовать подход API коллекций Java:
UnifiedMapmap = new UnifiedMap<>(); map.put(1, "one"); map.put(2, "two"); map.put(3, "three");
Поскольку неизменяемые коллекции не могут быть изменены, они не имеют реализаций методов, которые изменяют коллекции , таких как add() и remove() .
Неизменяемые коллекции, однако, позволяют нам вызывать эти методы, но вызовут Исключение UnsupportedOperationException если мы это сделаем.
5. Извлечение элементов из коллекций
Как и при использовании стандартных Списков , элементы коллекций Eclipse Списков могут быть извлечены по их индексу:
list.get(0);
А значения карт коллекций Eclipse можно получить с помощью их ключа:
map.get(0);
Методы getFirst() и getLast() могут использоваться для извлечения первого и последнего элементов списка соответственно. В случае других коллекций они возвращают первый и последний элемент, который будет возвращен итератором.
map.getFirst(); map.getLast();
Методы max() и min() можно использовать для получения максимальных и минимальных значений коллекции на основе естественного порядка.
map.max(); map.min();
6. Итерация по коллекции
Коллекции Eclipse предоставляют множество способов перебора коллекций. Давайте посмотрим, что это такое и как они работают на практике.
6.1. Фильтрация коллекций
Шаблон select возвращает новую коллекцию, содержащую элементы коллекции, удовлетворяющие логическому условию. По сути, это операция фильтрации.
Вот пример:
@Test public void givenListwhenSelect_thenCorrect() { MutableListgreaterThanThirty = 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() { MutableListnotGreaterThanThirty = list .reject(Predicates.greaterThan(30)) .sortThis(); Assertions.assertThat(notGreaterThanThirty) .containsExactlyElementsOf(this.expectedList); }
Здесь мы отвергаем все элементы, которые превышают 30.
6.2. Метод сбора()
Метод collect возвращает новую коллекцию, элементами которой являются результаты, возвращаемые предоставленным лямбда – выражением-по сути, это комбинация map() и collect() из Stream API.
Давайте посмотрим на это в действии:
@Test public void whenCollect_thenCorrect() { Student student1 = new Student("John", "Hopkins"); Student student2 = new Student("George", "Adams"); MutableListstudents = FastList .newListWith(student1, student2); MutableList lastNames = students .collect(Student::getLastName); Assertions.assertThat(lastNames) .containsExactly("Hopkins", "Adams"); }
Созданная коллекция фамилии содержит фамилии, собранные из списка студенты .
Но, что делать, если возвращаемая коллекция является коллекцией коллекций, и мы не хотим поддерживать вложенную структуру?
Например, если у каждого студента есть несколько адресов, и нам нужна коллекция, содержащая адреса в виде Строк , а не коллекция коллекций, мы можем использовать метод flatCollect () .
Вот пример:
@Test public void whenFlatCollect_thenCorrect() { MutableListaddresses = students .flatCollect(Student::getAddresses); Assertions.assertThat(addresses) .containsExactlyElementsOf(this.expectedAddresses); }
6.3. Обнаружение элементов
То обнаружить метод находит и возвращает первый элемент, удовлетворяющий логическому условию.
Давайте рассмотрим краткий пример:
@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); }
Аналогично, все Удовлетворяют метод определяет, удовлетворяют ли все элементы коллекции логическому условию.
Давайте рассмотрим краткий пример:
@Test public void whenAnySatisfiesCondition_thenCorrect() { boolean result = list.allSatisfy(Predicates.greaterThan(0)); assertTrue(result); }
6.4. Метод partition()
Метод partition выделяет каждый элемент коллекции в одну из двух коллекций в зависимости от того, удовлетворяет ли элемент логическому условию.
Давайте рассмотрим пример:
@Test public void whenAnySatisfiesCondition_thenCorrect() { MutableListnumbers = 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"); MutableListstudents = 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")); }
Здесь объект lazy Students не извлекает элементы списка students до тех пор, пока не будет вызван метод collect () .
7. Сопряжение элементов Коллекции
Метод zip() возвращает новую коллекцию, объединяя элементы двух коллекций в пары. Если какая-либо из двух коллекций длиннее, остальные элементы будут усечены.
Давайте посмотрим, как мы можем его использовать:
@Test public void whenZip_thenCorrect() { MutableListnumbers = 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() { MutableListcars = FastList .newListWith("Porsche", "Volvo", "Toyota"); MutableList > pairs = cars.zipWithIndex(); Assertions.assertThat(pairs) .containsExactlyElementsOf(this.expectedPairs); }
8. Преобразование коллекций
Коллекции Eclipse предоставляют простые методы преобразования типа контейнера в другой. Это методы ToList() , toSet() , tobago() и to Map().
Давайте посмотрим, как мы можем их использовать:
public static List convertToList() { UnifiedSetcars = new UnifiedSet<>(); cars.add("Toyota"); cars.add("Mercedes"); cars.add("Volkswagen"); return cars.toList(); }
Давайте проведем наш тест:
@Test public void whenConvertContainerToAnother_thenCorrect() { MutableListcars = (MutableList) ConvertContainerToAnother .convertToList(); Assertions.assertThat(cars) .containsExactlyElementsOf( FastList.newListWith("Volkswagen", "Toyota", "Mercedes")); }
9. Заключение
В этом руководстве мы увидели краткий обзор коллекций Eclipse и функций, которые они предоставляют.
Полная реализация этого учебника доступна на GitHub .