Java Comparar dos listas

92

Tengo dos listas (no listas de Java, puede decir dos columnas)

Por ejemplo

**List 1**            **Lists 2**
  milan                 hafil
  dingo                 iga
  iga                   dingo
  elpha                 binga
  hafil                 mike
  meat                  dingo
  milan
  elpha
  meat
  iga                   
  neeta.peeta    

Me gustaría un método que devuelva cuántos elementos son iguales. Para este ejemplo, debería ser 3 y debería devolverme valores similares de la lista y valores diferentes también.

¿Debo usar hashmap si es así, entonces qué método para obtener mi resultado?

Por favor ayuda

PD: No es una tarea de la escuela :) Así que si me guias será suficiente

user238384
fuente
Sugiera cualquier estructura de datos; la lista no es una lista java o hashmap o cualquier estructura de datos
user238384
1
Asegúrese de pensar en lo que debe hacer en casos excepcionales. ¿Pueden las listas contener el mismo valor dos veces? Si es así, si "dingo" está en ambas listas dos veces, ¿eso cuenta como dos elementos en común o solo como uno?
JavadocMD
¿Puede modificar uno de la lista?
Anthony Forloney
como editar ?? Sí, cada lista puede contener valores similares varias veces
usuario238384
Debe haber un pequeño enlace de edición justo después de la pregunta, debajo de las etiquetas.
OscarRyz

Respuestas:

159

EDITAR

Aquí hay dos versiones. Uno usando ArrayListy otro usandoHashSet

Compárelos y cree su propia versión a partir de esto, hasta que obtenga lo que necesita.

Esto debería ser suficiente para cubrir:

PD: No es una tarea de la escuela :) Así que si me guias será suficiente

parte de tu pregunta.

continuando con la respuesta original:

Puede usar ay java.util.Collection / o java.util.ArrayListpara eso.

El método keepAll hace lo siguiente:

Conserva solo los elementos de esta colección que están contenidos en la colección especificada

ver esta muestra:

import java.util.Collection;
import java.util.ArrayList;
import java.util.Arrays;

public class Repeated {
    public static void main( String  [] args ) {
        Collection listOne = new ArrayList(Arrays.asList("milan","dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta"));
        Collection listTwo = new ArrayList(Arrays.asList("hafil", "iga", "binga", "mike", "dingo"));

        listOne.retainAll( listTwo );
        System.out.println( listOne );
    }
}

EDITAR

Para la segunda parte (valores similares) puede utilizar el método removeAll :

Elimina todos los elementos de esta colección que también están contenidos en la colección especificada.

Esta segunda versión también le da valores similares y maneja repetidos (descartándolos).

Esta vez, Collectionpodría ser a en Setlugar de a List(la diferencia es que el conjunto no permite valores repetidos)

import java.util.Collection;
import java.util.HashSet;
import java.util.Arrays;

class Repeated {
      public static void main( String  [] args ) {

          Collection<String> listOne = Arrays.asList("milan","iga",
                                                    "dingo","iga",
                                                    "elpha","iga",
                                                    "hafil","iga",
                                                    "meat","iga", 
                                                    "neeta.peeta","iga");

          Collection<String> listTwo = Arrays.asList("hafil",
                                                     "iga",
                                                     "binga", 
                                                     "mike", 
                                                     "dingo","dingo","dingo");

          Collection<String> similar = new HashSet<String>( listOne );
          Collection<String> different = new HashSet<String>();
          different.addAll( listOne );
          different.addAll( listTwo );

          similar.retainAll( listTwo );
          different.removeAll( similar );

          System.out.printf("One:%s%nTwo:%s%nSimilar:%s%nDifferent:%s%n", listOne, listTwo, similar, different);
      }
}

Salida:

$ java Repeated
One:[milan, iga, dingo, iga, elpha, iga, hafil, iga, meat, iga, neeta.peeta, iga]

Two:[hafil, iga, binga, mike, dingo, dingo, dingo]

Similar:[dingo, iga, hafil]

Different:[mike, binga, milan, meat, elpha, neeta.peeta]

Si no hace exactamente lo que necesita, le da un buen comienzo para que pueda manejar desde aquí.

Pregunta para el lector: ¿Cómo incluiría todos los valores repetidos?

OscarRyz
fuente
@Oscar, mi pensamiento exacto, pero no estaba seguro de si podríamos haber modificado el contenido de listOne, ¡pero +1 de todos modos!
Anthony Forloney
@poygenelubricants ¿a qué te refieres con tipos crudos, no genéricos? Por qué no?
OscarRyz
Oscar, ¿viste mi pregunta actualizada? ¿Admite valores repetidos?
user238384
@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "Se desaconseja enfáticamente el uso de tipos sin procesar en el código escrito después de la introducción de la genéricaidad en el lenguaje de programación Java. Es posible que futuras versiones de el lenguaje de programación Java no permitirá el uso de tipos sin formato ".
polygenelubricants
2
Respuesta de @polygenelubricants actualizada para manejar duplicados y tipos sin procesar. Por cierto, la ..futura versión de Java ... nunca va a suceder. ;)
OscarRyz
37

Puede probar intersection()y subtract()métodos de CollectionUtils.

intersection()El método le brinda una colección que contiene elementos comunes y el subtract()método le brinda todos los poco comunes.

También deben cuidar elementos similares

Mihir Mathuria
fuente
6
Debe tener en cuenta que esta solución requiere Apache Ccommons
Sir Codesalot
9

¿Son estas realmente listas (ordenadas, con duplicados) o son conjuntos (desordenadas, sin duplicados)?

Porque si es lo último, entonces puede usar, digamos, ay java.util.HashSet<E>hacer esto en el tiempo lineal esperado usando el conveniente retainAll.

    List<String> list1 = Arrays.asList(
        "milan", "milan", "iga", "dingo", "milan"
    );
    List<String> list2 = Arrays.asList(
        "hafil", "milan", "dingo", "meat"
    );

    // intersection as set
    Set<String> intersect = new HashSet<String>(list1);
    intersect.retainAll(list2);
    System.out.println(intersect.size()); // prints "2"
    System.out.println(intersect); // prints "[milan, dingo]"

    // intersection/union as list
    List<String> intersectList = new ArrayList<String>();
    intersectList.addAll(list1);
    intersectList.addAll(list2);
    intersectList.retainAll(intersect);
    System.out.println(intersectList);
    // prints "[milan, milan, dingo, milan, milan, dingo]"

    // original lists are structurally unmodified
    System.out.println(list1); // prints "[milan, milan, iga, dingo, milan]"
    System.out.println(list2); // prints "[hafil, milan, dingo, meat]"
poligenelubricantes
fuente
bueno, realmente no sé qué estructura de datos debería ser. Tiene duplicados. Ahora puede ver la pregunta actualizada
user238384
¿Eliminará los valores repetidos del conjunto de datos? porque no quiero perder ningún valor :(
user238384
@agazerboy: He intentado abordar ambas preguntas. No dude en solicitar más aclaraciones.
polygenelubricants
gracias poli. Probé su programa con duplicados, por ejemplo, en la primera lista agregué "iga" dos veces, pero aún así me devuelve 3 como respuesta. Si bien debería ser 4 ahora. porque la lista 1 tiene 4 valores similares. Si agregué una entrada varias veces, debería funcionar. ¿Qué dices? ¿Alguna otra estructura de datos?
user238384
6

Usando java 8 removeIf

public int getSimilarItems(){
    List<String> one = Arrays.asList("milan", "dingo", "elpha", "hafil", "meat", "iga", "neeta.peeta");
    List<String> two = new ArrayList<>(Arrays.asList("hafil", "iga", "binga", "mike", "dingo")); //Cannot remove directly from array backed collection
    int initial = two.size();

    two.removeIf(one::contains);
    return initial - two.size();
}
Asanka Siriwardena
fuente
Se ve bien, pero si quiero mantener las listas sin modificar, tendría que clonar una de las listas y eso no sería deseable en ciertos casos.
Sebastian D'Agostino
6

Si está buscando una forma práctica de probar la igualdad de dos colecciones, puede usar org.apache.commons.collections.CollectionUtils.isEqualCollection, que compara dos colecciones independientemente del orden.

zorro de nieve
fuente
4

De todos los enfoques, encuentro que usar org.apache.commons.collections.CollectionUtils#isEqualCollectiones el mejor enfoque. Estas son las razones:

  • No tengo que declarar ninguna lista adicional / establecerme
  • No estoy mutando las listas de entrada.
  • Es muy eficiente. Comprueba la igualdad en la complejidad O (N).

Si no es posible tener apache.commons.collectionscomo dependencia, recomendaría implementar el algoritmo que sigue para verificar la igualdad de la lista debido a su eficiencia.

shakhawat
fuente
3

Solución simple :-

    List<String> list = new ArrayList<String>(Arrays.asList("a", "b", "d", "c"));
    List<String> list2 = new ArrayList<String>(Arrays.asList("b", "f", "c"));

    list.retainAll(list2);
    list2.removeAll(list);
    System.out.println("similiar " + list);
    System.out.println("different " + list2);

Salida: -

similiar [b, c]
different [f]
Opster Elasticsearch Pro-Vijay
fuente
1

Asumiendo hash1yhash2

List< String > sames = whatever
List< String > diffs = whatever

int count = 0;
for( String key : hash1.keySet() )
{
   if( hash2.containsKey( key ) ) 
   {
      sames.add( key );
   }
   else
   {
      diffs.add( key );
   }
}

//sames.size() contains the number of similar elements.
Stefan Kendall
fuente
Quiere la lista de claves idénticas, no cuántas claves son idénticas. Yo creo que.
Rosdi Kasim
Gracias stefan por tu ayuda. Sí, Rosdi tiene razón y tú también. Necesito el número total de valores similares y valores similares también.
user238384
1

Encontré un ejemplo muy básico de comparación de listas en Comparación de listas. Este ejemplo verifica primero el tamaño y luego verifica la disponibilidad del elemento particular de una lista en otra.

Manoj Kumar
fuente
-1
public static boolean compareList(List ls1, List ls2){
    return ls1.containsAll(ls2) && ls1.size() == ls2.size() ? true :false;
     }

public static void main(String[] args) {

    ArrayList<String> one = new ArrayList<String>();
    one.add("one");
    one.add("two");
    one.add("six");

    ArrayList<String> two = new ArrayList<String>();
    two.add("one");
    two.add("six");
    two.add("two");

    System.out.println("Output1 :: " + compareList(one, two));

    two.add("ten");

    System.out.println("Output2 :: " + compareList(one, two));
  }
Pavan Rangani
fuente
1
Esta solución devuelve el resultado incorrecto cuando dos contienen 3 copias de "uno". Produciría incorrectamente un resultado verdadero.
Joseph Fitzgerald
Gracias por esta parte: && ls1.size () == ls2.size ()
Nouar
1
¿Alguna razón que crea que ? true :falsees necesaria en su fragmento?
Krzysztof Tomaszewski