Como remover duplicatas de uma lista?

Eu quero remover duplicatas de uma lista, mas o que estou fazendo não está funcionando:

List listCustomer = new ArrayList(); for (Customer customer: tmpListCustomer) { if (!listCustomer.contains(customer)) { listCustomer.add(customer); } } 

Se esse código não funcionar, você provavelmente não implementou equals(Object) na class Customer apropriadamente.

Presumivelmente, há alguma chave (vamos chamá-lo customerId ) que identifica exclusivamente um cliente; por exemplo

 class Customer { private String customerId; ... 

Uma definição apropriada de equals(Object) seria assim:

  public boolean equals(Object obj) { if (obj == this) { return true; } if (!(obj instanceof Customer)) { return false; } Customer other = (Customer) obj; return this.customerId.equals(other.customerId); } 

Para completar, você também deve implementar o hashCode para que dois objects Customer iguais retornem o mesmo valor de hash. Um hashCode correspondente para a definição acima de equals seria:

  public int hashCode() { return customerId.hashCode(); } 

Também é importante notar que esta não é uma maneira eficiente de remover duplicatas se a lista for grande. (Para uma lista com N clientes, você precisará realizar N*(N-1)/2 comparações no pior caso, ou seja, quando não houver duplicatas.) Para uma solução mais eficiente, você deve usar algo como um HashSet para fazer a verificação duplicada.

Supondo que você queira manter o pedido atual e não quer um Set , talvez o mais fácil seja:

 List depdupeCustomers = new ArrayList<>(new LinkedHashSet<>(customers)); 

Se você quiser alterar a lista original:

 Set depdupeCustomers = new LinkedHashSet<>(customers); customers.clear(); customers.addAll(dedupeCustomers); 

atualização do java 8
você pode usar o stream da matriz como abaixo:

 Arrays.stream(yourArray).distinct() .collect(Collectors.toList()); 

O cliente implementa o contrato equals() ?

Se ele não implementar equals() e hashCode() , listCustomer.contains(customer) verificará se a mesma instância já existe na lista (Por exemplo, o mesmo object – endereço de memory, etc) ). Se o que você está procurando é testar se o mesmo cliente (talvez seja o mesmo cliente se eles tiverem o mesmo nome de cliente ou número de cliente) já está na lista, você precisará replace equals() para garantir que verifica se os campos relevantes (por exemplo, nomes de clientes) coincidem ou não.

Nota: Não se esqueça de replace o hashCode() se você for replace equals() ! Caso contrário, você pode ter problemas com seus HashMaps e outras estruturas de dados. Para uma boa cobertura de por que isso é e quais armadilhas evitar, considere dar uma olhada nos capítulos Java efetivos de Josh Bloch em equals() e hashCode() (O link contém apenas iformation sobre por que você deve implementar hashCode() ao implementar equals() , mas há uma boa cobertura sobre como replace equals() também).

By the way, existe uma restrição de encomenda no seu set? Se não houver, uma maneira um pouco mais fácil de resolver esse problema é usar um Set forma:

 Set noDups = new HashSet(); noDups.addAll(tmpListCustomer); return new ArrayList(noDups); 

Qual removerá duplicatas agradáveis ​​para você, desde que os grupos não permitem duplicatas. No entanto, isso perderá qualquer ordenação que tenha sido aplicada ao tmpListCustomer , já que o HashSet não tem ordenação explícita (você pode contornar isso usando um TreeSet , mas isso não está exatamente relacionado à sua pergunta). Isso pode simplificar seu código um pouco.

Listar → Definir → Listar (distinto)

Basta adicionar todos os seus elementos a um Set : ele não permite que seus elementos sejam repetidos. Se você precisar de uma lista depois, use o novo construtor ArrayList(theSet) depois (em que theSet é o seu conjunto resultante).

Eu suspeito que você pode não ter Customer.equals() implementado corretamente (ou em todos).

List.contains() usa equals() para verificar se algum de seus elementos é idêntico ao object passado como parâmetro. No entanto, a implementação padrão de testes de equals para identidade física, não identidade de valor. Portanto, se você não tiver sobrescrito no Customer , ele retornará false para dois objects distintos do Cliente que tenham um estado idêntico.

Aqui estão os detalhes básicos de como implementar equals (e hashCode , que é o seu par – você deve praticamente implementar ambos, se você precisar implementar qualquer um deles). Como você não nos mostrou a class Customer, é difícil dar conselhos mais concretos.

Como outros notaram, é melhor usar um conjunto do que fazer o trabalho manualmente, mas mesmo assim, você ainda precisa implementar esses methods.

O método “contém” pesquisou se a lista contém uma input que retorna true de Customer.equals (Objeto o). Se você não tiver substituído equals (Object) no Customer ou em um de seus pais, ele procurará somente por uma ocorrência existente do mesmo object. Pode ser que era isso que você queria, e nesse caso seu código deveria funcionar. Mas se você estava procurando não ter dois objects representando o mesmo cliente, então você precisa replace equals (Object) para retornar true quando for esse o caso.

Também é verdade que o uso de uma das implementações de Set em vez de List lhe daria uma remoção duplicada automaticamente e mais rápida (para qualquer outra coisa além de Lists muito pequenas). Você ainda precisará fornecer código para iguais.

Você também deve replace hashCode () ao replace equals ().

 private void removeTheDuplicates(ListmyList) { for(ListIteratoriterator = myList.listIterator(); iterator.hasNext();) { Customer customer = iterator.next(); if(Collections.frequency(myList, customer) > 1) { iterator.remove(); } } System.out.println(myList.toString()); } 

Duas sugestões:

  • Use um HashSet em vez de um ArrayList. Isso acelerará consideravelmente as verificações de contains () se você tiver uma lista longa

  • Certifique-se de que Customer.equals () e Customer.hashCode () sejam implementados corretamente, ou seja, eles devem ser baseados nos valores combinados dos campos subjacentes no object do cliente.

Quase todas as respostas acima estão corretas, mas o que eu sugiro é usar um mapa ou conjunto ao criar a lista relacionada, e não depois, para obter desempenho. Porque converter uma lista em um Set ou Map e reconvertê-la em uma List novamente é um trabalho trivial.

Código de amostra:

 Set stringsSet = new LinkedHashSet();//A Linked hash set //prevents the adding order of the elements for (String string: stringsList) { stringsSet.add(string); } return new ArrayList(stringsSet); 

Como outros já mencionaram, provavelmente você não está implementando equals () corretamente.

No entanto, você também deve observar que esse código é considerado bastante ineficiente, já que o tempo de execução pode ser o número de elementos ao quadrado.

Você pode querer considerar o uso de uma estrutura Set em vez de uma List, ou criar um Set primeiro e então transformá-lo em uma lista.

A maneira mais limpa é:

 List lstConsultada = dao.findByPropertyList(YYY); List lstFinal = new ArrayList(new LinkedHashSet(XXX)); 

e replace hascode e equals às propriedades do Id de cada entidade

Melhor maneira IMHO como fazê-lo nos dias de hoje:

Suponha que você tenha uma coleção ” dups ” e queira criar outra coleção contendo os mesmos elementos, mas com todas as duplicatas eliminadas. O seguinte one-liner faz o truque.

 Collection noDups = new HashSet(dups); 

Ele funciona criando um conjunto que, por definição, não pode conter duplicatas.

Baseado no oracle doc.

Usando o java 8 stream api.

  List list = new ArrayList<>(); list.add("one"); list.add("one"); list.add("two"); System.out.println(list); Collection c = list.stream().collect(Collectors.toSet()); System.out.println(c); 

Saída:

Antes dos valores: [um, um, dois]

Depois dos valores: [um, dois]

A resposta correta para Java é usar um conjunto . Se você já tem uma List e deseja duplicá-la

 Set s = new HashSet(listCustomer); 

Em outros casos, basta usar HashSet , TreeSet implementação do TreeSet diretamente e pular a fase de construção da List .

Você precisará sobrescrever hashCode() e equals() em suas classs de domínio que são colocadas no Set também para garantir que o comportamento desejado seja realmente o que você obtém. equals() pode ser tão simples quanto comparar ids únicos dos objects a tão complexos quanto comparar todos os campos. hashCode() pode ser tão simples quanto retornar o hashCode() do id exclusivo ‘ String representação ou o hashCode() .

 Class removeduplicates { public static void main(string args[[]) { int I; for(int =0;i'<10;I++) { system.out.println(+i); if([]I=[j]) { system.out.println(1,2,3,1,1,1,2,2,2) } } } }