Introdução
Neste laboratório, você aprenderá como verificar eficientemente se uma List Java contém elementos duplicados. Exploraremos uma técnica comum e eficaz que utiliza a estrutura de dados HashSet.
Primeiramente, você implementará um método que aproveita a propriedade de elementos únicos do HashSet para detectar duplicatas, iterando pela lista e adicionando elementos ao conjunto. Se um elemento já estiver presente no conjunto, uma duplicata é encontrada. Posteriormente, você aprenderá uma abordagem alternativa, comparando o tamanho da lista original com o tamanho de um HashSet preenchido com os elementos da lista. Finalmente, você testará sua implementação com vários cenários, incluindo listas nulas e vazias, para garantir a robustez.
Usar HashSet para Detecção de Duplicatas
Nesta etapa, exploraremos como usar um HashSet em Java para detectar eficientemente elementos duplicados dentro de uma coleção. HashSet faz parte do Java Collections Framework e é particularmente útil para armazenar elementos únicos.
Primeiro, vamos criar um novo arquivo Java chamado DuplicateDetector.java em seu diretório ~/project. Você pode fazer isso usando o File Explorer do WebIDE à esquerda. Clique com o botão direito na área ~/project, selecione "New File" e digite DuplicateDetector.java.
Agora, abra o arquivo DuplicateDetector.java no Code Editor e adicione o seguinte código:
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
public class DuplicateDetector {
public static boolean containsDuplicates(List<String> list) {
// Create a HashSet to store unique elements
Set<String> uniqueElements = new HashSet<>();
// Iterate through the list
for (String element : list) {
// If the element is already in the HashSet, it's a duplicate
if (uniqueElements.contains(element)) {
return true; // Found a duplicate
}
// Otherwise, add the element to the HashSet
uniqueElements.add(element);
}
// If the loop finishes without finding duplicates, return false
return false;
}
public static void main(String[] args) {
// Example usage
List<String> myListWithDuplicates = new ArrayList<>();
myListWithDuplicates.add("apple");
myListWithDuplicates.add("banana");
myListWithDuplicates.add("apple"); // Duplicate
myListWithDuplicates.add("orange");
List<String> myListWithoutDuplicates = new ArrayList<>();
myListWithoutDuplicates.add("grape");
myListWithoutDuplicates.add("mango");
myListWithoutDuplicates.add("kiwi");
System.out.println("List with duplicates: " + myListWithDuplicates);
System.out.println("Contains duplicates? " + containsDuplicates(myListWithDuplicates)); // Expected: true
System.out.println("\nList without duplicates: " + myListWithoutDuplicates);
System.out.println("Contains duplicates? " + containsDuplicates(myListWithoutDuplicates)); // Expected: false
}
}
Vamos entender as partes-chave deste código:
import java.util.ArrayList;,import java.util.HashSet;,import java.util.List;,import java.util.Set;: Estas linhas importam as classes necessárias do Java Collections Framework.public static boolean containsDuplicates(List<String> list): Este é um método que recebe umaListde objetosStringcomo entrada e retornatruese ela contém duplicatas, efalsecaso contrário.Set<String> uniqueElements = new HashSet<>();: Isso cria umHashSetvazio chamadouniqueElements.HashSeté projetado para armazenar apenas elementos únicos.for (String element : list): Este loop itera por cadaelementnalistde entrada.if (uniqueElements.contains(element)): Isso verifica se oelementatual já está presente noHashSetuniqueElements. Se estiver, significa que encontramos uma duplicata, e o método retornatrue.uniqueElements.add(element);: Se o elemento não estiver noHashSet, ele é adicionado. ComoHashSetarmazena apenas elementos únicos, adicionar um elemento que já está presente não tem efeito.return false;: Se o loop for concluído sem encontrar nenhuma duplicata, o método retornafalse.- O método
maindemonstra como usar o métodocontainsDuplicatescom listas de exemplo.
Salve o arquivo DuplicateDetector.java (Ctrl+S ou Cmd+S).
Agora, vamos compilar e executar este programa no Terminal. Certifique-se de estar no diretório ~/project.
Compile o código:
javac DuplicateDetector.java
Se não houver erros de compilação, você não verá nenhuma saída.
Agora, execute o código compilado:
java DuplicateDetector
Você deve ver uma saída semelhante a esta:
List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true
List without duplicates: [grape, mango, kiwi]
Contains duplicates? false
Esta saída confirma que nosso método containsDuplicates identificou corretamente a lista com duplicatas. Usar um HashSet é uma maneira eficiente de verificar duplicatas porque verificar a presença de um elemento em um HashSet (usando contains()) é muito rápido, em média.
Comparar o Tamanho da Lista com o Tamanho do Conjunto
Na etapa anterior, usamos um HashSet para verificar duplicatas iterando pela lista e adicionando elementos ao conjunto. Uma maneira mais simples e, muitas vezes, mais eficiente de detectar duplicatas é comparando o tamanho da lista original com o tamanho de um HashSet criado a partir dessa lista.
Lembre-se que um HashSet armazena apenas elementos únicos. Se uma lista contiver duplicatas, o tamanho de um HashSet criado a partir dessa lista será menor que o tamanho da lista original. Se não houver duplicatas, os tamanhos serão os mesmos.
Vamos modificar nosso arquivo DuplicateDetector.java para implementar essa abordagem. Abra ~/project/DuplicateDetector.java no Code Editor.
Substitua o método containsDuplicates pelo seguinte código:
public static boolean containsDuplicates(List<String> list) {
// Create a HashSet from the list
Set<String> uniqueElements = new HashSet<>(list);
// Compare the size of the list with the size of the HashSet
return list.size() != uniqueElements.size();
}
Aqui está o que está acontecendo no novo código:
Set<String> uniqueElements = new HashSet<>(list);: Esta linha cria diretamente umHashSete o inicializa com todos os elementos dalistde entrada. OHashSetlida automaticamente com a unicidade, então quaisquer elementos duplicados da lista não serão adicionados ao conjunto.return list.size() != uniqueElements.size();: Esta linha compara o número de elementos nalistoriginal (list.size()) com o número de elementos únicos noHashSet(uniqueElements.size()). Se os tamanhos forem diferentes (!=), significa que havia duplicatas na lista, e o método retornatrue. Se os tamanhos forem os mesmos, não havia duplicatas, e o método retornafalse.
O método main pode permanecer o mesmo, pois ele já chama o método containsDuplicates.
Salve o arquivo DuplicateDetector.java (Ctrl+S ou Cmd+S).
Agora, vamos compilar e executar o programa modificado. Certifique-se de estar no diretório ~/project no Terminal.
Compile o código:
javac DuplicateDetector.java
Execute o código compilado:
java DuplicateDetector
Você deve ver a mesma saída de antes:
List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true
List without duplicates: [grape, mango, kiwi]
Contains duplicates? false
Isso confirma que nosso novo método, mais simples, para detectar duplicatas usando a comparação de tamanho funciona corretamente. Essa abordagem é geralmente mais concisa e, muitas vezes, mais eficiente do que iterar e verificar a contenção um por um, especialmente para listas maiores.
Testar com Listas Nulas e Vazias
Na programação do mundo real, é importante considerar casos extremos (edge cases), como quando uma lista pode estar vazia ou até mesmo ser null. Nosso método containsDuplicates atual funciona bem para listas com elementos, mas o que acontece se passarmos uma lista vazia ou uma lista null?
Vamos testar isso adicionando mais exemplos ao nosso método main em ~/project/DuplicateDetector.java. Abra o arquivo no Code Editor e adicione as seguintes linhas ao método main, após o código existente:
System.out.println("\nEmpty list: " + new ArrayList<>());
System.out.println("Contains duplicates? " + containsDuplicates(new ArrayList<>())); // Expected: false
List<String> nullList = null;
System.out.println("\nNull list: " + nullList);
// The following line will cause a NullPointerException if not handled
// System.out.println("Contains duplicates? " + containsDuplicates(nullList));
Salve o arquivo (Ctrl+S ou Cmd+S).
Agora, compile e execute o programa novamente.
Compilar:
javac DuplicateDetector.java
Executar:
java DuplicateDetector
Você deve ver a saída para a lista vazia:
List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true
List without duplicates: [grape, mango, kiwi]
Contains duplicates? false
Empty list: []
Contains duplicates? false
A saída para a lista vazia está correta; uma lista vazia não contém duplicatas.
No entanto, se você descomentar a linha System.out.println("Contains duplicates? " + containsDuplicates(nullList)); e tentar compilar e executar, você obterá um NullPointerException. Isso acontece porque estamos tentando criar um HashSet a partir de uma lista null, o que não é permitido.
Para tornar nosso método containsDuplicates mais robusto, devemos tratar o caso em que a lista de entrada é null. Podemos adicionar uma verificação no início do método.
Modifique o método containsDuplicates em ~/project/DuplicateDetector.java para incluir uma verificação de nulo:
public static boolean containsDuplicates(List<String> list) {
// Handle null input
if (list == null) {
return false; // A null list does not contain duplicates
}
// Create a HashSet from the list
Set<String> uniqueElements = new HashSet<>(list);
// Compare the size of the list with the size of the HashSet
return list.size() != uniqueElements.size();
}
Agora, descomente a linha que testa a lista nula no método main:
List<String> nullList = null;
System.out.println("\nNull list: " + nullList);
System.out.println("Contains duplicates? " + containsDuplicates(nullList)); // Expected: false
Salve o arquivo (Ctrl+S ou Cmd+S).
Compile e execute o programa pela última vez.
Compilar:
javac DuplicateDetector.java
Executar:
java DuplicateDetector
A saída agora deve incluir o resultado para a lista nula sem travar:
List with duplicates: [apple, banana, apple, orange]
Contains duplicates? true
List without duplicates: [grape, mango, kiwi]
Contains duplicates? false
Empty list: []
Contains duplicates? false
Null list: null
Contains duplicates? false
Ao adicionar a verificação de nulo, nosso método containsDuplicates agora é mais robusto e pode lidar com a entrada null de forma adequada. Esta é uma prática importante na programação para evitar erros inesperados.
Resumo
Neste laboratório, aprendemos como verificar se uma List Java contém elementos duplicados. Exploramos o uso de um HashSet para detecção eficiente de duplicatas. Ao iterar pela lista e tentar adicionar cada elemento a um HashSet, podemos determinar rapidamente se um elemento já está presente, indicando uma duplicata.
Também aprendemos um método alternativo, comparando o tamanho da lista original com o tamanho de um HashSet criado a partir da lista. Se os tamanhos forem diferentes, isso significa a presença de duplicatas. Finalmente, consideramos casos extremos (edge cases) testando os métodos com listas nulas e vazias para garantir a robustez.



