Java confronta due elenchi


92

Ho due elenchi (non elenchi Java, puoi dire due colonne)

Per esempio

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

Mi piacerebbe un metodo che restituisca quanti elementi sono uguali. Per questo esempio dovrebbe essere 3 e dovrebbe restituirmi valori simili sia dell'elenco che di valori diversi.

Devo usare hashmap se sì, allora quale metodo per ottenere il mio risultato?

Per favore aiuto

PS: Non è un compito scolastico :) Quindi se mi guidi solo sarà sufficiente


Si prega di suggerire qualsiasi struttura di dati che l'elenco non sia un elenco java o hashmap o qualsiasi struttura di dati
user238384

1
Assicurati di pensare a cosa dovresti fare in casi eccezionali. Gli elenchi possono contenere lo stesso valore due volte? In tal caso, se "dingo" è in entrambe le liste due volte, conta come due elementi in comune o solo uno?
JavadocMD

Puoi modificare uno degli elenchi?
Anthony Forloney

come modificare ?? Sì, ogni elenco può contenere valori simili più volte
user238384

Dovrebbe esserci un piccolo collegamento di modifica subito dopo la domanda, sotto i tag.
OscarRyz

Risposte:


159

MODIFICARE

Ecco due versioni. Uno usando ArrayListe l'altro usandoHashSet

Confrontarli e creare la propria versione di questo, fino ad ottenere quello che ti serve.

Questo dovrebbe essere sufficiente per coprire:

PS: Non è un compito scolastico :) Quindi se mi guidi solo sarà sufficiente

parte della tua domanda.

continuando con la risposta originale:

Puoi usare un java.util.Collection e / o java.util.ArrayListper quello.

Il metodo keepAll esegue le seguenti operazioni:

Conserva solo gli elementi di questa raccolta che sono contenuti nella raccolta specificata

guarda questo esempio:

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 );
    }
}

MODIFICARE

Per la seconda parte (valori simili) puoi usare il metodo removeAll :

Rimuove tutti gli elementi di questa raccolta che sono contenuti anche nella raccolta specificata.

Questa seconda versione fornisce anche i valori simili e le maniglie ripetute (scartandole).

Questa volta Collectionpotrebbe essere a Setinvece di a List(la differenza è che il Set non consente valori ripetuti)

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);
      }
}

Produzione:

$ 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]

Se non fa esattamente quello che ti serve, ti dà un buon inizio in modo da poter gestire da qui.

Domanda per il lettore: come includeresti tutti i valori ripetuti?


@Oscar, il mio pensiero esatto, ma non ero sicuro se avremmo potuto modificare il contenuto di listOne, ma +1 comunque!
Anthony Forloney

@poygenelubricants cosa intendi per tipi grezzi non generici? Perchè no?
OscarRyz

Oscar, hai visto la mia domanda aggiornata? Supporta valori ripetuti?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "L'uso di tipi grezzi nel codice scritto dopo l'introduzione della genericità nel linguaggio di programmazione Java è fortemente sconsigliato. È possibile che versioni future di il linguaggio di programmazione Java non consentirà l'uso di tipi non elaborati. "
polygenelubricants

2
Risposta di @polygenelubricants aggiornata per gestire duplicati e tipi non elaborati. A proposito, la ... versione futura di Java ... non accadrà mai. ;)
OscarRyz


9

Queste sono davvero liste (ordinate, con duplicati) o sono insiemi (non ordinati, nessun duplicato)?

Perché se è il secondo, puoi usare, diciamo, a java.util.HashSet<E>e farlo nel tempo lineare previsto usando il 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]"

beh, davvero non so quale struttura dati dovrebbe essere. Ha duplicati. Ora puoi vedere la domanda aggiornata
user238384

Rimuoverà i valori ripetuti dal set di dati? perché non voglio perdere alcun valore :(
user238384

@agazerboy: ho cercato di rispondere a entrambe le domande. Sentiti libero di chiedere ulteriori chiarimenti.
polygenelubricants

grazie poli. Ho provato il tuo programma con i duplicati, ad esempio nel primo elenco ho aggiunto "iga" due volte ma comunque mi restituisce 3 come risposta. Mentre ora dovrebbero essere 4. coz list 1 ha 4 valori simili. Se ho aggiunto una voce più volte dovrebbe funzionare. Che ne dici? Qualche altra struttura dati?
user238384

6

Utilizzando 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();
}

Sembra buono, ma se voglio mantenere le liste invariate dovrei clonare una delle liste e ciò non sarebbe desiderato in alcuni casi.
Sebastian D'Agostino

6

Se stai cercando un modo pratico per testare l'uguaglianza di due raccolte, puoi utilizzare org.apache.commons.collections.CollectionUtils.isEqualCollection, che confronta due raccolte indipendentemente dall'ordinamento.


4

Di tutti gli approcci, trovo che l'uso org.apache.commons.collections.CollectionUtils#isEqualCollectionsia l'approccio migliore. Ecco i motivi:

  • Non devo dichiarare alcun elenco / set aggiuntivo da solo
  • Non sto modificando gli elenchi di input
  • È molto efficiente. Controlla l'uguaglianza nella complessità O (N).

Se non è possibile avere apache.commons.collectionscome dipendenza, consiglierei di implementare l'algoritmo che segue per verificare l'uguaglianza della lista a causa della sua efficienza.


3

Soluzione semplice: -

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

Produzione :-

similiar [b, c]
different [f]

1

Supponendo hash1ehash2

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.

Vuole l'elenco delle chiavi identiche, non quante chiavi sono identiche. Penso.
Rosdi Kasim

Grazie stefan per il tuo aiuto. Sì, Rosdi ha ragione e anche tu. Ho bisogno del numero totale di valori simili e anche di valori simili.
user238384

1

Ho trovato un esempio molto semplice di confronto elenco in Confronta elenco Questo esempio verifica prima la dimensione e quindi controlla la disponibilità del particolare elemento di un elenco in un altro.


-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));
  }

1
Questa soluzione restituisce il risultato sbagliato quando due contengono 3 copie di "uno". Produrrebbe erroneamente un risultato reale.
Joseph Fitzgerald

Grazie per questa parte: && ls1.size () == ls2.size ()
Nouar

1
C'è qualche motivo per cui pensi ? true :falsesia necessario nel tuo snippet?
Krzysztof Tomaszewski
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.