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.