Java Zwei Listen vergleichen


92

Ich habe zwei Listen (keine Java-Listen, man kann zwei Spalten sagen)

Beispielsweise

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

Ich möchte eine Methode, die zurückgibt, wie viele Elemente gleich sind. In diesem Beispiel sollte es 3 sein und mir ähnliche Werte sowohl für die Liste als auch für unterschiedliche Werte zurückgeben.

Sollte ich eine Hashmap verwenden, wenn ja, welche Methode, um mein Ergebnis zu erhalten?

Bitte helfen Sie

PS: Es ist keine Schulaufgabe :) Wenn du mich also nur führst, wird es ausreichen


Bitte schlagen Sie eine Datenstruktur vor, bei der es sich bei der Liste nicht um eine Java-Liste oder eine Hashmap oder eine Datenstruktur handelt
user238384

1
Überlegen Sie sich in Ausnahmefällen, was Sie tun sollten. Können Listen zweimal denselben Wert enthalten? Wenn ja, wenn "Dingo" zweimal in beiden Listen enthalten ist, zählt dies als zwei gemeinsame Elemente oder nur als eines?
JavadocMD

Können Sie eine der Listen ändern?
Anthony Forloney

Wie bearbeite ich? Ja, jede Liste kann
mehrmals

Direkt nach der Frage sollte sich unter den Tags ein kleiner Link zum Bearbeiten befinden .
OscarRyz

Antworten:


159

BEARBEITEN

Hier sind zwei Versionen. Eine Verwendung ArrayListund eine andere VerwendungHashSet

Vergleichen Sie sie und erstellen Sie daraus Ihre eigene Version, bis Sie das bekommen, was Sie brauchen.

Dies sollte ausreichen, um Folgendes abzudecken:

PS: Es ist keine Schulaufgabe :) Wenn du mich also nur führst, wird es ausreichen

Teil Ihrer Frage.

Fortsetzung der ursprünglichen Antwort:

Sie können ein java.util.Collection und / oder verwenden java.util.ArrayList dafür verwenden.

Die RetainAll- Methode führt Folgendes aus:

Behält nur die Elemente in dieser Sammlung bei, die in der angegebenen Sammlung enthalten sind

siehe dieses Beispiel:

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

BEARBEITEN

Für den zweiten Teil (ähnliche Werte) können Sie die removeAll- Methode verwenden:

Entfernt alle Elemente dieser Sammlung, die auch in der angegebenen Sammlung enthalten sind.

Diese zweite Version gibt Ihnen auch die ähnlichen Werte und Handles wiederholt (indem Sie sie verwerfen).

Diesmal Collectionkönnte das ein Setstatt eines sein List(der Unterschied ist, dass das Set keine wiederholten Werte zulässt)

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

Ausgabe:

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

Wenn es nicht genau das tut, was Sie brauchen, haben Sie einen guten Start, damit Sie von hier aus damit umgehen können.

Frage an den Leser: Wie würden Sie alle wiederholten Werte einbeziehen?


@Oscar, mein genauer Gedanke, aber ich war mir nicht sicher, ob wir den Inhalt von hätten listOneändern können, aber trotzdem +1!
Anthony Forloney

@poygenelubricants was meinst du mit rohen Typen, nicht mit Generika? Warum nicht?
OscarRyz

Oscar, hast du meine aktualisierte Frage gesehen? Unterstützt es wiederholte Werte?
user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "Die Verwendung von Rohtypen in Code, der nach der Einführung der Generizität in die Java-Programmiersprache geschrieben wurde, wird dringend empfohlen. Es ist möglich, dass zukünftige Versionen von Die Java-Programmiersprache verbietet die Verwendung von Rohtypen. "
Polygenschmierstoffe

2
Die Antwort von @polygenelubricants wurde aktualisiert, um Duplikate und Rohtypen zu verarbeiten. Übrigens , die zukünftige Version von Java wird niemals passieren. ;)
OscarRyz


9

Sind das wirklich Listen (geordnet, mit Duplikaten) oder sind sie Mengen (ungeordnet, keine Duplikate)?

Denn wenn es das letztere ist, können Sie beispielsweise a verwenden java.util.HashSet<E>und dies in der erwarteten linearen Zeit mit dem praktischen tun 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]"

Nun, ich weiß wirklich nicht, welche Datenstruktur es sein soll. Es hat Duplikate. Jetzt können Sie aktualisierte Frage sehen
user238384

Werden die wiederholten Werte aus dem Datensatz entfernt? coz Ich möchte keinen Wert
verlieren

@agazerboy: Ich habe versucht, beide Fragen zu beantworten. Fühlen Sie sich frei, um weitere Klarstellungen zu bitten.
Polygenschmierstoffe

danke poly. Ich habe Ihr Programm mit Duplikaten ausprobiert, zum Beispiel in der ersten Liste. Ich habe zweimal "iga" hinzugefügt, aber es gibt mir trotzdem 3 als Antwort zurück. Während es jetzt 4 sein sollte. Coz Liste 1 hat 4 ähnliche Werte. Wenn ich einen Eintrag mehrmals hinzugefügt habe, sollte es funktionieren. Was sagst du? Irgendeine andere Datenstruktur?
user238384

6

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

Es sieht gut aus, aber wenn ich die Listen unverändert lassen möchte, müsste ich eine der Listen klonen, und das wäre in bestimmten Fällen nicht erwünscht.
Sebastian D'Agostino

6

Wenn Sie nach einer praktischen Möglichkeit suchen, die Gleichheit zweier Sammlungen zu testen, können Sie diese verwenden org.apache.commons.collections.CollectionUtils.isEqualCollection, um zwei Sammlungen unabhängig von der Reihenfolge zu vergleichen.


4

Von allen Ansätzen finde ich, dass org.apache.commons.collections.CollectionUtils#isEqualCollectionder beste Ansatz ist. Hier sind die Gründe -

  • Ich muss keine zusätzliche Liste deklarieren / mich selbst einstellen
  • Ich mutiere die Eingabelisten nicht
  • Es ist sehr effizient. Es überprüft die Gleichheit in der O (N) -Komplexität.

Wenn es nicht möglich ist, apache.commons.collectionseine Abhängigkeit zu haben , würde ich empfehlen, den folgenden Algorithmus zu implementieren, um die Gleichheit der Liste aufgrund ihrer Effizienz zu überprüfen.


3

Einfache Lösung: -

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

Ausgabe :-

similiar [b, c]
different [f]

1

Vorausgesetzt hash1undhash2

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.

Er möchte die Liste der identischen Schlüssel, nicht wie viele Schlüssel identisch sind. Meiner Ansicht nach.
Rosdi Kasim

Danke stefan für deine hilfe. Ja, Rosdi ist richtig und du auch. Ich benötige die Gesamtzahl ähnlicher Werte und ähnlicher Werte.
user238384

1

Ich habe ein sehr einfaches Beispiel für einen Listenvergleich bei List Compare gefunden. In diesem Beispiel wird zuerst die Größe überprüft und dann die Verfügbarkeit des jeweiligen Elements einer Liste in einer anderen überprüft.


-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
Diese Lösung gibt das falsche Ergebnis zurück, wenn zwei drei Kopien von "eins" enthalten. Es würde fälschlicherweise ein echtes Ergebnis liefern.
Joseph Fitzgerald

Vielen Dank für diesen Teil: && ls1.size () == ls2.size ()
Nouar

1
Gibt es einen Grund, für den Sie denken ? true :false, dass er in Ihrem Snippet benötigt wird?
Krzysztof Tomaszewski
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.