Conjunto de Coleções Apache Commons

Conjunto de Coleções Apache Commons

1. Visão geral

Neste artigo, exploraremos a APISetUtils da biblioteca de coleções do Apache Commons. Simplificando, esses utilitários podem ser usados ​​para executar certas operações nas estruturas de dadosSet em Java.

2. Instalação de Dependências

Para usarmos a bibliotecaSetUtils em nosso projeto, precisamos adicionar a seguinte dependência ao arquivopom.xml de nosso projeto:


    org.apache.commons
    commons-collections4
    4.1

Alternativamente, se nosso projeto for baseado em Gradle, devemos adicionar a dependência ao arquivobuild.gradle do nosso projeto. Além disso, precisamos adicionarmavenCentral() à seção de repositórios do arquivobuild.gradle:

compile 'org.apache.commons:commons-collections4:4.1'

3. Conjunto Predicado

O métodopredicatedSet() da bibliotecaSetUtils permite definir condições que devem ser atendidas por todos os elementos que devem ser inseridos em um conjunto. Ele aceita um objeto de origemSet e um predicado.

Podemos usar isso para validar facilmente se todos os elementos de aSet satisfazem uma determinada condição, o que pode ser útil ao desenvolver uma biblioteca / API de terceiros.

Se a validação falhar para qualquer elemento, umIllegalArgumentException será lançado. O snippet abaixo deprevents the addition ofstrings that do not start with ‘L' emsourceSet ouvalidatingSet retornado:

Set validatingSet
  = SetUtils.predicatedSet(sourceSet, s -> s.startsWith("L"));

A biblioteca também tempredicatedSortedSet()epredicatedNavigableSet() para trabalhar comSortedSeteNavigableSet respectivamente.

4. União, diferença e intersecção de um conjunto

A biblioteca possui métodos que podem calcular a união, diferença e a interseção de elementosSet.

O métododifference() pega dois objetosSet e retorna um objetoSetUtils.SetView imutável. OSetUtils.SetView retornado contém os elementos que estão no conjuntoa, mas não no conjuntob:

Set a = new HashSet<>(Arrays.asList(1, 2, 5));
Set b = new HashSet<>(Arrays.asList(1, 2));
SetUtils.SetView result = SetUtils.difference(a, b);

assertTrue(result.size() == 1 && result.contains(5));

Observe que,trying to perform write operations, like add() or addAll(), on the returned SetUtils.SetView will throw an UnsupportedOperationException.

Para modificar o resultado retornado, precisamos chamar o métodotoSet() doSetUtils.SetView retornado para obter um objetoSet gravável:

Set mutableSet = result.toSet();

O métodounion da bibliotecaSetUtils faz exatamente o que parece - retorna todos os elementos do conjuntoaeb. O métodounion também retorna um objetoSetUtil.SetView que é imutável:

Set expected = new HashSet<>(Arrays.asList(1, 2, 5));
SetUtils.SetView union = SetUtils.union(a, b);

assertTrue(SetUtils.isEqualSet(expected, union));

Take note of the isEqualSet() method usado na instrução assert. É um método estático conveniente da bibliotecaSetUtils que verifica efetivamente se dois conjuntos são iguais.

Para obter a interseção de um conjunto, ou seja, elementos que estão presentes no conjuntoa no conjuntob, usaremos o métodoSetUtils.intersection(). Este método também retorna um objetoSetUtil.SetView:

Set expected = new HashSet<>(Arrays.asList(1, 2));
SetUtils.SetView intersect = SetUtils.intersection(a, b);

assertTrue(SetUtils.isEqualSet(expected, intersect));

5. Elementos do conjunto de transformação

Vamos dar uma olhada em outro método interessante -SetUtils.transformedSet(). Este método aceita um objetoSet e uma interfaceTransformer. Apoiado pelo conjunto de origem, ele usa o métodotransform() da interfaceTransformer para transformar cada elemento de um conjunto.

A lógica de transformação é definida no métodotransform() da interfaceTransformer, que se aplica a cada elemento adicionado ao conjunto. O snippet de código abaixo multiplica todos os elementos adicionados ao conjunto por 2:

Set a = SetUtils.transformedSet(new HashSet<>(), e -> e * 2  );
a.add(2);

assertEquals(a.toArray()[0], 4);

O métodotransformedSet() é muito útil - eles podem até ser usados ​​para lançar elementos de um conjunto - digamos de String para Integer. Apenas certifique-se de que o tipo de saída seja um subtipo da entrada.

Digamos que estejamos trabalhando comSortedSet ouNavigableSet em vez deHashSet,, podemos usartransformedSortedSet() outransformedNavigableSet() respectivamente.

Observe que uma nova instânciaHashSet é passada para o métodotransformedSet(). Em situações em que umSet existente e não vazio é passado para o método, os elementos pré-existentes não serão transformados.

Se quisermos transformar elementos pré-existentes (e aqueles adicionados posteriormente), precisamos usar o métodotransformedSet() deorg.apache.commons.collections4.set.TransformedSet:

Set source = new HashSet<>(Arrays.asList(1));
Set newSet = TransformedSet.transformedSet(source, e -> e * 2);

assertEquals(newSet.toArray()[0], 2);
assertEquals(source.toArray()[0], 2);

Observe que os elementos do conjunto de origem são transformados e o resultado é copiado para onewSet. retornado

6. Definir disjunção

A bibliotecaSetUtils fornece um método estático que pode ser usado para encontrar disjunções de conjuntos. A disjunção do conjuntoa e do conjuntob são todos os elementos exclusivos para o conjunto a e o conjunto b.

Vamos ver como usar o métododisjunction() da bibliotecaSetUtils:

Set a = new HashSet<>(Arrays.asList(1, 2, 5));
Set b = new HashSet<>(Arrays.asList(1, 2, 3));
SetUtils.SetView result = SetUtils.disjunction(a, b);

assertTrue(
  result.toSet().contains(5) && result.toSet().contains(3));

7. Outros métodos na bibliotecaSetUtils

Existem outros métodos na bibliotecaSetUtils que tornam o processamento dos dados definidos uma brisa:

  • Podemos usarsynchronizedSet() ousynchronizedSortedSet() para obter umSet thread-safe. No entanto, conforme declarado nos documentos, nósmust manually synchronize o iterador do conjunto retornado para evitar comportamento não determinístico

  • Podemos usarSetUtils.unmodifiableSet() para obter um conjunto somente leitura. Observe que uma tentativa de adicionar elementos ao objetoSet retornado lançará umUnsupportedOperationException

  • Há também o métodoSetUtils.emptySet() que retorna um conjunto vazio imutável e seguro para o tipo

  • O métodoSetUtils.emptyIfNull() aceita um objetoSet anulável. Ele retorna um vazio, somente leitura, Set se oSet fornecido for nulo; caso contrário, ele retorna oSet fornecido

  • SetUtils.orderedSet() retornará um objetoSet que mantém a ordem em que os elementos são adicionados

  • SetUtils.hashCodeForSet() pode gerar um hashcode para um conjunto - de modo que dois conjuntos dos mesmos elementos tenham o mesmo hashcode

  • SetUtils.newIdentityHashSet() retornará umHashSet que usa== para corresponder a um elemento em vez do métodoequals(). Por favor, leia sobre suas advertênciashere

8. Conclusão

Neste artigo, exploramos os detalhes da bibliotecaSetUtils. A classe de utilitário oferece métodos estáticos que tornam o trabalho com uma estrutura de dados definida fácil e interessante. Também aumenta a produtividade.

Como sempre, trechos de código estão disponíveisover on GitHub. O documento oficial para a APISetUtils pode serfound here.