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() {
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 возвращает новую коллекцию, элементами которой являются результаты, возвращаемые предоставленным лямбда – выражением-по сути, это комбинация 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");
} Созданная коллекция фамилии содержит фамилии, собранные из списка студенты .
Но, что делать, если возвращаемая коллекция является коллекцией коллекций, и мы не хотим поддерживать вложенную структуру?
Например, если у каждого студента есть несколько адресов, и нам нужна коллекция, содержащая адреса в виде Строк , а не коллекция коллекций, мы можем использовать метод flatCollect () .
Вот пример:
@Test
public void whenFlatCollect_thenCorrect() {
MutableList addresses = 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() {
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"));
} Здесь объект lazy Students не извлекает элементы списка 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 предоставляют простые методы преобразования типа контейнера в другой. Это методы ToList() , toSet() , tobago() и to Map().
Давайте посмотрим, как мы можем их использовать:
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 и функций, которые они предоставляют.
Полная реализация этого учебника доступна на GitHub .