Рубрики
Без рубрики

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

Краткое и практическое руководство по коллекции сумок от Apache Commons.

Автор оригинала: baeldung.

1. введение

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

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

Apache Commons BeanUtils

Apache Commons IO

Введение в текст Apache Commons

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

Прежде чем мы начнем, нам нужно импортировать последние зависимости из 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. Нарушения Договора инкассации

При чтении документации API Bag мы можем заметить, что некоторые методы помечены как нарушающие стандартный контракт на сбор данных Java.

Например, когда мы используем add() API из коллекции 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 предоставляет декоратор, называемый Collection Bag. Мы можем использовать это, чтобы сделать наши коллекции сумок совместимыми с контрактом Java Collection :

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

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

4. Реализация Пакетов

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

4.1. Хэштег

Мы можем добавить элемент и указать 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. Древесный мешок

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

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

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:

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 – Коллекций.synchronizedSortedMap() и TreeMap – для имитации того, что мы сделали здесь с SynchronizedSortedBag .

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

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

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