Pregunta

¿Cómo podría ir sobre la detección (volviendo verdadero / falso) si un ArrayList contiene más de un elemento de la misma en Java?

Muchas gracias, Terry

Editar Se me olvidó mencionar que no estoy búsqueda de ofertas de "Bloques" entre sí, pero sus valores enteros. Cada "bloque" tiene un int y esto es lo que los hace diferentes. Encuentro la int de un bloque particular, llamando a un método llamado "getNum" (por ejemplo, tabla1 [0] [2] .getNum ();

¿Fue útil?

Solución

Más simple:. Volcar toda la colección en un conjunto (con el Set () constructor de colección o Set.addAll), y luego ver si el conjunto tiene el mismo tamaño que el ArrayList

List<Integer> list = ...;
Set<Integer> set = new HashSet<Integer>(list);

if(set.size() < list.size()){
    /* There are duplicates */
}

Actualización: Si yo estoy entendiendo bien su pregunta, tiene una matriz 2D del bloque, como en

tabla de bloque de [] [];

y desea detectar si cualquier fila de ellos tiene duplicados?

En ese caso, podría hacer lo siguiente, suponiendo que el Bloque implementa "es igual a" y "código hash" correctamente:

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

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

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

Set.add devuelve falso un valor lógico si se agrega el elemento está ya en el conjunto, por lo que podría incluso cortocircuito y la bala a cabo en cualquier complemento que devuelve false si todo lo que quiere saber es si hay duplicados.

Otros consejos

Mejora de código, usando el valor de retorno de Set#add en lugar de comparar el tamaño de la lista y configurar.

public static <T> boolean hasDuplicate(Iterable<T> all) {
    Set<T> set = new HashSet<T>();
    // 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 usted está buscando para evitar tener duplicados en absoluto, entonces sólo debe cortar a cabo el proceso de detección de duplicados media y utilizar un conjunto .

Código mejorado para devolver los elementos duplicados

  • Puede encontrar duplicados en una colección
  • devuelve el conjunto de duplicados
  • elementos singulares se puede obtener de la Set

public static <T> List getDuplicate(Collection<T> list) {

    final List<T> duplicatedObjects = new ArrayList<T>();
    Set<T> set = new HashSet<T>() {
    @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 <T> boolean hasDuplicate(Collection<T> list) {
    if (getDuplicate(list).isEmpty())
        return false;
    return true;
}

Si los elementos son de alguna manera comparable (el hecho de que la orden tiene ningún significado real es indiferente - sólo tiene que ser consistente con su definición de igualdad), la solución más rápida eliminación de duplicados va a ordenar la lista (0 ( n log (n))), entonces hay que hacer una sola pasada y busque repiten elementos (es decir, los elementos iguales que siguen entre sí) (esto es O (n)).

La complejidad general va a ser O (n log (n)), que es más o menos lo mismo que lo que se obtendría con un conjunto (n veces larga (n)), pero con una constante mucho más pequeño. Esto se debe a la constante en ordenar / resultados dedup desde el costo de la comparación de elementos, mientras que el coste del conjunto es más probable que el resultado de un cálculo de hash, más uno (posiblemente varias) comparaciones de patata. Si está utilizando una aplicación Conjunto basado en hash, es decir, debido a que un árbol sobre la base va a darle un O (n log² (n)), lo que es aún peor.

A mi entender, sin embargo, no es necesario para eliminar duplicados, sino que simplemente prueba de su existencia. Por lo que debe codificar manualmente un algoritmo de fusión o de pila de clasificación en la matriz, que simplemente se sale de regresar verdadera (es decir, "no es un DUP") si su comparador devuelve 0, y de otra manera completa la especie, y atravesar la prueba matriz ordenada para las repeticiones . O en una combinación de pila de clasificación, de hecho, cuando se completa la especie, se han comparado cada par duplicado a menos que ambos elementos ya estaban en sus posiciones finales (que es poco probable). Por lo tanto, un algoritmo de tipo tweaked debe producir una enorme mejora del rendimiento (que tendría que demostrar que, pero supongo que el algoritmo tweaked debe estar en el O (log (n)) en los datos de manera uniforme al azar)

que tenía que hacer una operación similar para un Stream, pero no pude encontrar un buen ejemplo. Esto es lo que ocurrió.

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

Esto tiene la ventaja de cortocircuito cuando los duplicados se detectan a tiempo en lugar de tener que procesar toda la corriente y no es mucho más complicado que simplemente poner todo en un Set y comprobar el tamaño. Por lo que este caso sería más o menos ser:

List<T> list = ...
boolean allDistinct = areUnique(list.stream());

Con Java 8+ puede utilizar la API de corriente:

boolean areAllDistinct(List<Block> blocksList) {
    return blocksList.stream().map(Block::getNum).distinct().count() == blockList.size();
}

En pocas palabras: 1) asegurarse de que todos los artículos son comparables 2) ordenar la matriz 2) iterar sobre la matriz y encontrar duplicados

Para conocer los duplicados en una lista utilice el código siguiente: Se le dará el conjunto que contiene duplicados

.
 public Set<?> findDuplicatesInList(List<?> beanList) {
    System.out.println("findDuplicatesInList::"+beanList);
    Set<Object> duplicateRowSet=null;
    duplicateRowSet=new LinkedHashSet<Object>();
            for(int i=0;i<beanList.size();i++){
                Object superString=beanList.get(i);
                System.out.println("findDuplicatesInList::superString::"+superString);
                for(int j=0;j<beanList.size();j++){
                    if(i!=j){
                         Object subString=beanList.get(j);
                         System.out.println("findDuplicatesInList::subString::"+subString);
                         if(superString.equals(subString)){
                             duplicateRowSet.add(beanList.get(j));
                         }
                    }
                }
            }
            System.out.println("findDuplicatesInList::duplicationSet::"+duplicateRowSet);
        return duplicateRowSet;
  }

mejor manera de manejar este problema es utilizar un HashSet

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

Sólo imprimir resultado ArrayList y ver el resultado sin duplicados:)

Si desea que el conjunto de valores duplicados:

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<String> uniqueSet = new HashSet<String>();
        List<String> dupesList = new ArrayList<String>();
        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);
    }
}

Y probablemente también pensar en el recorte de los valores o el uso de minúsculas ... dependiendo de su caso.

    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 rendimiento mayor éxito, aunque como se quitan elementos de principio de la lista. Para hacer frente a esto, tenemos dos opciones. 1) iterar en orden inverso y eliminar elementos. 2) Uso LinkedList en lugar de ArrayList. Debido a las preguntas formuladas en entrevistas sesgadas para eliminar los duplicados de la lista sin necesidad de utilizar cualquier otra colección, el ejemplo anterior es la respuesta. En el mundo real, sin embargo, si tengo que conseguir esto, voy a poner los elementos de la lista para establecer, 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 <T> boolean hasDuplicates(List<T> list){
        int count = list.size();
        T t1,t2;

        for(int i=0;i<count;i++){
            t1 = list.get(i);
            for(int j=i+1;j<count;j++){
                t2 = list.get(j);
                if(t2.equals(t1)){
                    return true;
                }
            }
        }
        return false;
    }

Un ejemplo de una clase concreta que se ha anulado 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;
    }
}
    ArrayList<String> withDuplicates = new ArrayList<>();
    withDuplicates.add("1");
    withDuplicates.add("2");
    withDuplicates.add("1");
    withDuplicates.add("3");
    HashSet<String> set = new HashSet<>(withDuplicates);
    ArrayList<String> withoutDupicates = new ArrayList<>(set);

    ArrayList<String> duplicates = new ArrayList<String>();

    Iterator<String> 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);

Esta respuesta está escrita en Kotlin, pero puede ser fácilmente traducido a Java.

Si el tamaño de su ArrayList está dentro de un pequeño rango fijo, entonces esta es una gran solución.

var duplicateDetected = false
    if(arrList.size > 1){
        for(i in 0 until arrList.size){
            for(j in 0 until arrList.size){
                if(i != j && arrList.get(i) == arrList.get(j)){
                    duplicateDetected = true
                }
            }
        }
    }
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top