Java: detectar duplicados en ArrayList?

¿Cómo podría hacer para detectar (devolver verdadero / falso) si una ArrayList contiene más de uno del mismo elemento en Java?

Muchas gracias, Terry

Editar Olvidé mencionar que no estoy buscando comparar “Bloques” entre sí, sino sus valores enteros. Cada “bloque” tiene un int y esto es lo que los hace diferentes. Encontré el int de un Bloque en particular llamando a un método llamado “getNum” (por ejemplo, table1 [0] [2] .getNum ();

Lo más simple: volcar toda la colección en un conjunto (usando el constructor Set (Collection) o Set.addAll), luego ver si el conjunto tiene el mismo tamaño que el ArrayList.

List list = ...; Set set = new HashSet(list); if(set.size() < list.size()){ /* There are duplicates */ } 

Actualización: si entiendo tu pregunta correctamente, tienes una matriz 2d de Bloque, como en

Tabla de bloques [] [];

y quieres detectar si alguna fila de ellos tiene duplicados?

En ese caso, podría hacer lo siguiente, suponiendo que Block implemente correctamente "equals" y "hashCode":

 for (Block[] row : table) { Set set = new HashSet(); for (Block cell : row) { set.add(cell); } if (set.size() < 6) { //has duplicate } } 

No estoy 100% seguro de eso para la syntax, por lo que podría ser más seguro escribirlo como

 for (int i = 0; i < 6; i++) { Set set = new HashSet(); for (int j = 0; j < 6; j++) set.add(table[i][j]); 

...

Código mejorado, utilizando el valor de retorno de Set#add lugar de comparar el tamaño de la lista y el conjunto.

 public static  boolean hasDuplicate(Iterable all) { Set set = new HashSet(); // Set#add returns false if the set does not change, which // indicates that a duplicate element has been added. for (T each: all) if (!set.add(each)) return true; return false; } 

Si está buscando evitar tener duplicados, entonces simplemente debe cortar el proceso intermedio de detección de duplicados y usar un conjunto .

Código mejorado para devolver los elementos duplicados

  • Puede encontrar duplicados en una colección
  • devolver el conjunto de duplicados
  • Los elementos únicos se pueden obtener del conjunto

 public static  List getDuplicate(Collection list) { final List duplicatedObjects = new ArrayList(); Set set = new HashSet() { @Override public boolean add(T e) { if (contains(e)) { duplicatedObjects.add(e); } return super.add(e); } }; for (T t : list) { set.add(t); } return duplicatedObjects; } public static  boolean hasDuplicate(Collection list) { if (getDuplicate(list).isEmpty()) return false; return true; } 

Si sus elementos son de alguna manera Comparables (el hecho de que la orden tenga algún significado real es indiferente, solo debe ser consistente con su definición de igualdad), la solución de eliminación de duplicados más rápida va a ordenar la lista (0 (n log ( n))) luego para hacer una sola pasada y buscar elementos repetidos (es decir, elementos iguales que se suceden entre sí) (esto es O (n)).

La complejidad general será O (n log (n)), que es aproximadamente la misma que obtendría con un conjunto (n veces de largo (n)), pero con una constante mucho menor. Esto se debe a que la constante en sort / dedup resulta del costo de comparar elementos, mientras que el costo del conjunto es más probable que resulte de un cálculo de hash, más una (posiblemente varias) comparaciones de hash. Si está utilizando una implementación de conjunto basada en hash, es decir, porque un árbol basado le dará un O (n log² (n)), que es aún peor.

Sin embargo, como yo lo entiendo, no es necesario eliminar duplicados, sino simplemente probar su existencia. Por lo tanto, debe codificar manualmente un algoritmo de fusión o agrupamiento en su matriz, que simplemente abandona el retorno verdadero (es decir, “hay un dup”) si su comparador devuelve 0 y completa el ordenamiento, y recorre la matriz ordenada probando repeticiones . En una fusión o tipo de stack, de hecho, cuando se completa el género, habrá comparado cada par duplicado a menos que ambos elementos ya estén en sus posiciones finales (lo cual es poco probable). Por lo tanto, un algoritmo de clasificación ajustado debería producir una gran mejora en el rendimiento (tendría que demostrarlo, pero supongo que el algoritmo ajustado debería estar en el O (log (n)) en datos uniformemente aleatorios)

Necesitaba hacer una operación similar para un Stream , pero no pude encontrar un buen ejemplo. Esto es lo que se me ocurrió.

 public static  boolean areUnique(final Stream stream) { final Set seen = new HashSet<>(); return stream.allMatch(seen::add); } 

Esto tiene la ventaja de cortocircuitar cuando los duplicados se encuentran temprano en lugar de tener que procesar toda la secuencia y no es mucho más complicado que simplemente poner todo en un Set y verificar el tamaño. Entonces este caso sería aproximadamente:

 List list = ... boolean allDistinct = areUnique(list.stream()); 

En pocas palabras: 1) asegúrese de que todos los elementos sean comparables 2) ordene la matriz 2) itere sobre la matriz y encuentre duplicados

Para saber los duplicados en una lista, use el siguiente código: le dará el conjunto que contiene duplicados.

  public Set findDuplicatesInList(List beanList) { System.out.println("findDuplicatesInList::"+beanList); Set duplicateRowSet=null; duplicateRowSet=new LinkedHashSet(); for(int i=0;i 


  String tempVal = null; for (int i = 0; i < l.size(); i++) { tempVal = l.get(i); //take the ith object out of list while (l.contains(tempVal)) { l.remove(tempVal); //remove all matching entries } l.add(tempVal); //at last add one entry } 

Nota: esto tendrá un mayor rendimiento aunque los artículos se eliminen del inicio de la lista. Para abordar esto, tenemos dos opciones. 1) iterar en orden inverso y eliminar elementos. 2) Use LinkedList en lugar de ArrayList. Debido a las preguntas sesgadas que se hacen en las entrevistas para eliminar duplicados de List sin utilizar ninguna otra colección, el ejemplo anterior es la respuesta. Sin embargo, en el mundo real, si tengo que lograr esto, pondré elementos de List to Set, ¡simple!

 /** * Method to detect presence of duplicates in a generic list. * Depends on the equals method of the concrete type. make sure to override it as required. */ public static  boolean hasDuplicates(List list){ int count = list.size(); T t1,t2; for(int i=0;i 

Un ejemplo de una clase concreta que ha reemplazado equals() :

 public class Reminder{ private long id; private int hour; private int minute; public Reminder(long id, int hour, int minute){ this.id = id; this.hour = hour; this.minute = minute; } @Override public boolean equals(Object other){ if(other == null) return false; if(this.getClass() != other.getClass()) return false; Reminder otherReminder = (Reminder) other; if(this.hour != otherReminder.hour) return false; if(this.minute != otherReminder.minute) return false; return true; } } 
 import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; public class FindDuplicateInArrayList { public static void main(String[] args) { Set uniqueSet = new HashSet(); List dupesList = new ArrayList(); for (String a : args) { if (uniqueSet.contains(a)) dupesList.add(a); else uniqueSet.add(a); } System.out.println(uniqueSet.size() + " distinct words: " + uniqueSet); System.out.println(dupesList.size() + " dupesList words: " + dupesList); } } 
  ArrayList withDuplicates = new ArrayList<>(); withDuplicates.add("1"); withDuplicates.add("2"); withDuplicates.add("1"); withDuplicates.add("3"); HashSet set = new HashSet<>(withDuplicates); ArrayList withoutDupicates = new ArrayList<>(set); ArrayList duplicates = new ArrayList(); Iterator dupIter = withDuplicates.iterator(); while(dupIter.hasNext()) { String dupWord = dupIter.next(); if(withDuplicates.contains(dupWord)) { duplicates.add(dupWord); }else{ withoutDupicates.add(dupWord); } } System.out.println(duplicates); System.out.println(withoutDupicates); 

La mejor manera de manejar este problema es usar un HashSet :

 ArrayList listGroupCode = new ArrayList<>(); listGroupCode.add("A"); listGroupCode.add("A"); listGroupCode.add("B"); listGroupCode.add("C"); HashSet set = new HashSet<>(listGroupCode); ArrayList result = new ArrayList<>(set); 

Simplemente imprime la lista de resultados y mira el resultado sin duplicados 🙂