Сумка для коллекций Apache Commons

Сумка для коллекций Apache Commons

1. Вступление

В этой быстрой статье мы сосредоточимся на том, как использовать коллекцию ApacheBag.

Дальнейшее чтение:

Apache Commons BeanUtils

Узнайте, как использовать Apache Commons BeanUtils для обычных операций с компонентами.

Read more

Apache Commons IO

Краткое и практическое руководство по библиотеке с открытым исходным кодом Apache Commons IO для Java, охватывающее многие из ее наиболее известных функций.

Read more

Введение в Apache Commons Text

Узнайте, как использовать Apache Commons Text для обычных операций со строками.

Read more

2. Maven Dependency

Прежде чем мы начнем, нам нужно импортировать последние зависимости изMaven Central:


    org.apache.commons
    commons-collections4
    4.1

3. Сумки против коллекций

Проще говоря,Bag - это коллекция, которая позволяет хранить несколько элементов вместе с их количеством повторений:

public void whenAdded_thenCountIsKept() {
    Bag bag = new HashBag<>(
      Arrays.asList(1, 2, 3, 3, 3, 1, 4));

    assertThat(2, equalTo(bag.getCount(1)));
}

3.1. Нарушения контрактаCollection

Читая документацию по APIBag, мы можем заметить, что некоторые методы помечены как нарушающие стандартный контракт Java Collection.

Например, когда мы используем APIadd() из коллекции Java, мы получаемtrue, даже если элемент уже находится в коллекции:

Collection collection = new ArrayList<>();
collection.add(1);
assertThat(collection.add(1), is(true));

Тот же API из реализацииBag вернетfalse, когда мы добавим элемент, который уже доступен в коллекции:

Bag bag = new HashBag<>();
bag.add(1);

assertThat(bag.add(1), is(not(true)));

Чтобы решить эти проблемы, библиотека Apache Collections предоставляет декоратор под названиемCollectionBag.. Мы можем использовать его, чтобы сделать наши коллекции пакетов совместимыми с контрактом JavaCollection:

public void whenBagAddAPILikeCollectionAPI_thenTrue() {
    Bag bag = CollectionBag.collectionBag(new HashBag<>());
    bag.add(1);

    assertThat(bag.add(1), is((true)));
}

4. Реализации мешков

Теперь давайте рассмотрим различные реализации интерфейсаBag в библиотеке коллекций Apache.

4.1. HashBagс

Мы можем добавить элемент и указать API количество копий, которое этот элемент должен иметь в нашей коллекции пакетов:

public void givenAdd_whenCountOfElementsDefined_thenCountAreAdded() {
    Bag bag = new HashBag<>();

    bag.add(1, 5); // adding 1 five times

    assertThat(5, equalTo(bag.getCount(1)));
}

Мы также можем удалить определенное количество копий или каждый экземпляр элемента из нашей сумки:

public void givenMultipleCopies_whenRemove_allAreRemoved() {
    Bag bag = new HashBag<>(
      Arrays.asList(1, 2, 3, 3, 3, 1, 4));

    bag.remove(3, 1); // remove one element, two still remain
    assertThat(2, equalTo(bag.getCount(3)));

    bag.remove(1); // remove all
    assertThat(0, equalTo(bag.getCount(1)));
}

4.2. TreeBagс

РеализацияTreeBag работает как любое другое дерево, дополнительно поддерживая семантикуBag.

Мы можем естественно отсортировать массив целых чисел с помощьюTreeBag, а затем запросить количество экземпляров каждого отдельного элемента в коллекции:

public void givenTree_whenDuplicateElementsAdded_thenSort() {
    TreeBag bag = new TreeBag<>(Arrays.asList(7, 5,
      1, 7, 2, 3, 3, 3, 1, 4, 7));

    assertThat(bag.first(), equalTo(1));
    assertThat(bag.getCount(bag.first()), equalTo(2));
    assertThat(bag.last(), equalTo(7));
    assertThat(bag.getCount(bag.last()), equalTo(3));
}

TreeBag реализует интерфейсSortedBag, все реализации этого интерфейса могут использовать декораторCollectionSortedBag для соблюдения контракта Java Collections:

public void whenTreeAddAPILikeCollectionAPI_thenTrue() {
    SortedBag bag
      = CollectionSortedBag.collectionSortedBag(new TreeBag<>());

    bag.add(1);

    assertThat(bag.add(1), is((true)));
}

4.3. SynchronizedSortedBagс

Другой широко используемой реализациейBag являетсяSynchronizedSortedBag. Точнее, это синхронизированный декоратор реализацииSortedBag.

Мы можем использовать этот декоратор с нашимTreeBag (реализацияSortedBag) из предыдущего раздела, чтобы синхронизировать доступ к нашей сумке:

public void givenSortedBag_whenDuplicateElementsAdded_thenSort() {
    SynchronizedSortedBag bag = SynchronizedSortedBag
      .synchronizedSortedBag(new TreeBag<>(
        Arrays.asList(7, 5, 1, 7, 2, 3, 3, 3, 1, 4, 7)));

    assertThat(bag.first(), equalTo(1));
    assertThat(bag.getCount(bag.first()), equalTo(2));
    assertThat(bag.last(), equalTo(7));
    assertThat(bag.getCount(bag.last()), equalTo(3));
}

Мы можем использовать комбинацию API -Collections.synchronizedSortedMap() иTreeMap –, чтобы имитировать то, что мы сделали здесь сSynchronizedSortedBag.

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

В этом коротком руководстве мы узнали об интерфейсеBag и его различных реализациях.

Как всегда, код этой статьи можно найтиover on GitHub.