Руководство по коллекциям Apache Commons CollectionUtils

Руководство по коллекциям Apache Commons CollectionUtils

1. обзор

Проще говоря,ApacheCollectionUtils предоставляет служебные методы для общих операций, которые охватывают широкий спектр вариантов использования и помогают избежать написания шаблонного кода. Библиотека нацелена на более старые версии JVM, поскольку в настоящее время аналогичная функциональность обеспечивается APIStreamв Java 8.

2. Maven Зависимости

Нам нужно добавить следующую зависимость, чтобы начать сCollectionUtils:


    org.apache.commons
    commons-collections4
    4.1

Последнюю версию библиотеки можно найтиhere.

3. Настроить

ДобавимCustomer иAddress classes:

public class Customer {
    private Integer id;
    private String name;
    private Address address;

    // standard getters and setters
}

public class Address {
    private String locality;
    private String city;

    // standard getters and setters
}

Мы также будем держать под рукой следующие экземплярыCustomer иList, готовые для тестирования нашей реализации:

Customer customer1 = new Customer(1, "Daniel", "locality1", "city1");
Customer customer2 = new Customer(2, "Fredrik", "locality2", "city2");
Customer customer3 = new Customer(3, "Kyle", "locality3", "city3");
Customer customer4 = new Customer(4, "Bob", "locality4", "city4");
Customer customer5 = new Customer(5, "Cat", "locality5", "city5");
Customer customer6 = new Customer(6, "John", "locality6", "city6");

List list1 = Arrays.asList(customer1, customer2, customer3);
List list2 = Arrays.asList(customer4, customer5, customer6);
List list3 = Arrays.asList(customer1, customer2);

List linkedList1 = new LinkedList<>(list1);

4. CollectionUtilsс

Давайте рассмотрим некоторые из наиболее часто используемых методов в классеApache Commons CollectionUtils.

4.1. Добавление только ненулевых элементов

Мы можем использовать методCollectionUtils’s addIgnoreNull, чтобы добавить в предоставленную коллекцию только ненулевые элементы.

Первый аргумент этого метода - это коллекция, в которую мы хотим добавить элемент, а второй аргумент - это элемент, который мы хотим добавить:

@Test
public void givenList_whenAddIgnoreNull_thenNoNullAdded() {
    CollectionUtils.addIgnoreNull(list1, null);

    assertFalse(list1.contains(null));
}

Обратите внимание, чтоnull не был добавлен в список.

4.2. Списки сортировки

We can use collate method to collate two already sorted lists. Этот метод принимает оба списка, которые мы хотим объединить, в качестве аргументов и возвращает один отсортированный список:

@Test
public void givenTwoSortedLists_whenCollated_thenSorted() {
    List sortedList = CollectionUtils.collate(list1, list2);

    assertEquals(6, sortedList.size());
    assertTrue(sortedList.get(0).getName().equals("Bob"));
    assertTrue(sortedList.get(2).getName().equals("Daniel"));
}

4.3. Преобразование объектов

Мы можем использовать методtransform для преобразования объектов класса A в различные объекты класса B. Этот метод принимает в качестве аргументов список объектов класса A иtransformer.

Результатом этой операции является список объектов класса B:

@Test
public void givenListOfCustomers_whenTransformed_thenListOfAddress() {
    Collection
addressCol = CollectionUtils.collect(list1, new Transformer() { public Address transform(Customer customer) { return customer.getAddress(); } }); List
addressList = new ArrayList<>(addressCol); assertTrue(addressList.size() == 3); assertTrue(addressList.get(0).getLocality().equals("locality1")); }

4.4. Фильтрация объектов

Using filter we can remove objects which do not satisfy a given condition from a list. Метод принимает список в качестве первого аргумента иPredicate в качестве второго аргумента.

The filterInverse method does the opposite. Удаляет объекты из списка, когдаPredicate возвращает истину.

Иfilter, иfilterInverse возвращаютtrue, если входной список был изменен, т.е. если хотя бы один объект был отфильтрован из списка:

@Test
public void givenCustomerList_WhenFiltered_thenCorrectSize() {

    boolean isModified = CollectionUtils.filter(linkedList1,
      new Predicate() {
        public boolean evaluate(Customer customer) {
            return Arrays.asList("Daniel","Kyle").contains(customer.getName());
        }
    });

    assertTrue(linkedList1.size() == 2);
}

Мы можем использоватьselect иselectRejected, если хотим, чтобы возвращался результирующий список, а не логический флаг.

4.5. Проверка на непустой

The isNotEmpty method is quite handy when we want to check if there is at least single element in a list. Другой способ проверить то же самое:

boolean isNotEmpty = (list != null && list.size() > 0);

Хотя приведенная выше строка кода делает то же самое,CollectionUtils.isNotEmpty сохраняет наш код более чистым:

@Test
public void givenNonEmptyList_whenCheckedIsNotEmpty_thenTrue() {
    assertTrue(CollectionUtils.isNotEmpty(list1));
}

The isEmpty does the opposite. Проверяет, является ли данный список нулевым или в нем нулевые элементы:

List emptyList = new ArrayList<>();
List nullList = null;

assertTrue(CollectionUtils.isEmpty(nullList));
assertTrue(CollectionUtils.isEmpty(emptyList));

4.6. Проверка включения

Мы можем использоватьisSubCollection, чтобы проверить, содержится ли коллекция в другой коллекции. isSubCollection принимает две коллекции в качестве аргументов и возвращаетtrue, если первая коллекция является подколлекцией второй коллекции:

@Test
public void givenCustomerListAndASubcollection_whenChecked_thenTrue() {
    assertTrue(CollectionUtils.isSubCollection(list3, list1));
}

Коллекция является вложенной коллекцией другой коллекции, если число раз, когда объект встречается в первой коллекции, меньше или равно числу раз, которое он встречает во второй коллекции.

4.7. Пересечение коллекций

We can use CollectionUtils.intersection method to get the intersection of two collections. Этот метод принимает две коллекции и возвращает набор элементов, общих для обеих входных коллекций:

@Test
public void givenTwoLists_whenIntersected_thenCheckSize() {
    Collection intersection = CollectionUtils.intersection(list1, list3);
    assertTrue(intersection.size() == 2);
}

Количество случаев, когда элемент встречается в результирующей коллекции, является минимальным числом случаев, когда он встречается в каждой из заданных коллекций.

4.8. Вычитание коллекций

CollectionUtils.subtract принимает две коллекции в качестве входных и возвращает коллекцию, которая содержит элементы, которые есть в первой коллекции, но не во второй коллекции:

@Test
public void givenTwoLists_whenSubtracted_thenCheckElementNotPresentInA() {
    Collection result = CollectionUtils.subtract(list1, list3);
    assertFalse(result.contains(customer1));
}

Число раз, когда коллекция встречается в результате, - это количество раз, которое она встречается в первой коллекции, минус количество раз, когда это происходит во второй коллекции.

4.9. Союз Коллекций

CollectionUtils.union объединяет две коллекции и возвращает коллекцию, содержащую все элементы, которые присутствуют в первой или второй коллекции.

@Test
public void givenTwoLists_whenUnioned_thenCheckElementPresentInResult() {
    Collection union = CollectionUtils.union(list1, list2);

    assertTrue(union.contains(customer1));
    assertTrue(union.contains(customer4));
}

Количество раз, которое элемент встречается в результирующей коллекции, является максимальным числом случаев, когда он встречается в каждой из заданных коллекций.

5. Заключение

И мы сделали.

Мы рассмотрели некоторые из наиболее часто используемых методовCollectionUtils, которые очень полезны, чтобы избежать использования шаблонов при работе с коллекциями в наших проектах Java.

Как обычно, доступен кодover on GitHub.