Saco das coleções de Apache Commons

Saco das coleções de Apache Commons

1. Introdução

Neste artigo rápido, vamos nos concentrar em como usar a coleçãoBag do Apache.

Leitura adicional:

Apache Commons BeanUtils

Aprenda a usar o Apache Commons BeanUtils para operações de bean comum.

Read more

Apache Commons IO

Um guia rápido e prático da biblioteca de código-fonte aberto Apache Commons IO para Java, cobrindo muitos de seus recursos mais conhecidos.

Read more

Introdução ao Apache Commons Text

Aprenda a usar o Apache Commons Text para operações comuns de String.

Read more

2. Dependência do Maven

Antes de começar, precisamos importar as dependências mais recentes deMaven Central:


    org.apache.commons
    commons-collections4
    4.1

3. Sacos vs coleções

Simplificando,Bag é uma coleção que permite armazenar vários itens junto com sua contagem de repetição:

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. Violações do ContratoCollection

Ao ler a documentação da API deBag, podemos notar que alguns métodos estão marcados como violando o contrato de coleção padrão do Java.

Por exemplo, quando usamos uma APIadd() de uma coleção Java, recebemostrue mesmo se o item já estiver na coleção:

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

A mesma API de uma implementaçãoBag retornará umfalse quando adicionarmos um elemento que já está disponível na coleção:

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

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

Para resolver esses problemas, a biblioteca de coleções do Apache fornece um decorador chamadoCollectionBag.. Podemos usar isso para tornar nossas coleções de bolsas compatíveis com o contrato JavaCollection:

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

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

4. Implementações de bolsas

Vamos agora explorar as várias implementações da interfaceBag - dentro da biblioteca de coleções do Apache.

4.1. HashBag

Podemos adicionar um elemento e instruir a API sobre o número de cópias que esse elemento deve ter em nossa coleção de malas:

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

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

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

Também podemos excluir um número específico de cópias ou todas as instâncias de um elemento da nossa bolsa:

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

A implementação deTreeBag funciona como qualquer outra árvore, mantendo adicionalmente a semântica deBag.

Podemos naturalmente classificar uma matriz de inteiros com umTreeBage, em seguida, consultar o número de instâncias que cada elemento individual possui na coleção:

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));
}

OTreeBag implementa uma interfaceSortedBag, todas as implementações dessa interface podem usar o decoradorCollectionSortedBag para cumprir o contrato de coleções Java:

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

    bag.add(1);

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

4.3. SynchronizedSortedBag

Outra implementação amplamente usada deBag é oSynchronizedSortedBag. Precisamente, este é um decorador sincronizado de uma implementaçãoSortedBag.

Podemos usar este decorador com nossoTreeBag (uma implementação deSortedBag) da seção anterior para sincronizar o acesso à nossa bolsa:

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));
}

Podemos usar uma combinação de APIs -Collections.synchronizedSortedMap()eTreeMap – para simular o que fizemos aqui comSynchronizedSortedBag.

5. Conclusão

Neste breve tutorial, aprendemos sobre a interfaceBag e suas várias implementações.

Como sempre, o código deste artigo pode ser encontradoover on GitHub.