Сумка для коллекций Apache Commons
1. Вступление
В этой быстрой статье мы сосредоточимся на том, как использовать коллекцию ApacheBag.
Дальнейшее чтение:
Apache Commons BeanUtils
Узнайте, как использовать Apache Commons BeanUtils для обычных операций с компонентами.
Apache Commons IO
Краткое и практическое руководство по библиотеке с открытым исходным кодом Apache Commons IO для Java, охватывающее многие из ее наиболее известных функций.
Введение в Apache Commons Text
Узнайте, как использовать Apache Commons Text для обычных операций со строками.
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.