Java Porównaj dwie listy


92

Mam dwie listy (nie listy java, możesz powiedzieć dwie kolumny)

Na przykład

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

Chciałbym metodę, która zwraca, ile elementów jest takich samych. W tym przykładzie powinno to być 3 i powinno zwrócić mi podobne wartości zarówno listy, jak i różne wartości.

Czy powinienem użyć hashmap, jeśli tak, to jaka metoda uzyskania wyniku?

Proszę pomóż

PS: To nie jest zadanie szkolne :) Więc jeśli mnie poprowadzisz, to wystarczy


Proszę zasugerować jakąkolwiek strukturę danych, lista nie jest listą java, hashmap ani żadną strukturą danych
— user238384

1
Pamiętaj, aby pomyśleć o tym, co powinieneś zrobić w wyjątkowych przypadkach. Czy listy mogą zawierać tę samą wartość dwukrotnie? Jeśli tak, jeśli „dingo” występuje na obu listach dwukrotnie, czy liczy się to jako dwa wspólne elementy, czy tylko jeden?
— JavadocMD

Czy możesz zmodyfikować jedną z list?
— Anthony Forloney

jak edytować? Tak, każda lista może zawierać podobne wartości wielokrotnie
— user238384

Zaraz po pytaniu, poniżej tagów, powinien znajdować się link edytuj .
— OscarRyz

Odpowiedzi:


160

EDYTOWAĆ

Oto dwie wersje. Jeden używający ArrayListi inny używającyHashSet

Porównaj je i stwórz z tego własną wersję, aż uzyskasz to, czego potrzebujesz.

To powinno wystarczyć do pokrycia:

PS: To nie jest zadanie szkolne :) Więc jeśli mnie poprowadzisz, to wystarczy

część twojego pytania.

kontynuując pierwotną odpowiedź:

Możesz użyć do tego a java.util.Collection i / lub java.util.ArrayList.

Metoda retainAll wykonuje następujące czynności:

Zachowuje tylko elementy w tej kolekcji, które znajdują się w określonej kolekcji

zobacz tę próbkę:

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

EDYTOWAĆ

W drugiej części (podobne wartości) możesz użyć metody removeAll :

Usuwa wszystkie elementy tej kolekcji, które są również zawarte w określonej kolekcji.

Ta druga wersja podaje również podobne wartości i uchwyty powtórzone (odrzucając je).

Tym razem Collectionmoże to być a Setzamiast a List(różnica polega na tym, że zestaw nie pozwala na powtarzanie wartości)

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

Wynik:

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

Jeśli nie robi dokładnie tego, czego potrzebujesz, daje ci dobry początek, więc możesz sobie z tym poradzić.

Pytanie do czytelnika: Jak zawarłbyś wszystkie powtarzające się wartości?


@Oscar, moja dokładna myśl, ale nie byłem pewien, czy moglibyśmy zmodyfikować zawartość listOne, ale i tak +1!
— Anthony Forloney

@poygenelubricants co masz na myśli przez typy surowe, a nie generyczne? Dlaczego nie?
— OscarRyz

Oscar, czy widziałeś moje zaktualizowane pytanie? Czy obsługuje powtarzające się wartości?
— user238384

@Oscar: java.sun.com/docs/books/jls/third_edition/html/… "Używanie surowych typów w kodzie napisanym po wprowadzeniu ogólności do języka programowania Java jest zdecydowanie odradzane. Możliwe, że przyszłe wersje język programowania Java nie zezwoli na używanie typów surowych ”.
— smary wielogenowe

2
Odpowiedź @polygenelubricants zaktualizowana w celu obsługi duplikatów i typów nieprzetworzonych. A tak przy okazji, ... przyszła wersja Java ... nigdy się nie wydarzy. ;)
— OscarRyz


9

Czy to naprawdę listy (uporządkowane, z duplikatami), czy też są to zestawy (nieuporządkowane, bez duplikatów)?

Bo jeśli jest to drugie, możesz użyć, powiedzmy, java.util.HashSet<E>ai zrobić to w oczekiwanym czasie liniowym, używając wygodnego 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]"

cóż, naprawdę nie wiem, jaka to powinna być struktura danych. Ma duplikaty. Teraz możesz zobaczyć zaktualizowane pytanie
— user238384

Czy usunie powtarzające się wartości ze zbioru danych? bo nie chcę stracić żadnej wartości :(
— user238384

@agazerboy: Próbowałem odpowiedzieć na oba pytania. Nie wahaj się poprosić o więcej wyjaśnień.
— smary wielogenowe

dzięki poli. Wypróbowałem twój program z duplikatami, na przykład na pierwszej liście dwa razy dodałem "iga", ale nadal zwracają mi 3 jako odpowiedź. Chociaż teraz powinno być 4. lista coz 1 ma 4 podobne wartości. Jeśli dodałem jeden wpis wielokrotnie, to powinno działać. Co mówisz? Jakaś inna struktura danych?
— user238384

6

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

Wygląda dobrze, ale jeśli chcę zachować niezmodyfikowane listy, musiałbym sklonować jedną z nich, co w niektórych przypadkach byłoby niepożądane.
— Sebastian D'Agostino

6

Jeśli szukasz wygodnego sposobu na przetestowanie równości dwóch kolekcji, możesz skorzystać z narzędzia org.apache.commons.collections.CollectionUtils.isEqualCollection, które porównuje dwie kolekcje niezależnie od kolejności.


4

Ze wszystkich podejść uważam, że używanie org.apache.commons.collections.CollectionUtils#isEqualCollectionjest najlepszym podejściem. Oto powody -

  • Nie muszę samodzielnie deklarować żadnej dodatkowej listy / zestawu
  • Nie zmieniam list wejściowych
  • Jest bardzo wydajna. Sprawdza równość w złożoności O (N).

Jeśli nie można mieć apache.commons.collectionsjako zależności, polecam zaimplementować algorytm, który następuje, aby sprawdzić równość listy ze względu na jej wydajność.


3

Proste rozwiązanie: -

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

Wynik :-

similiar [b, c]
different [f]

1

Zakładając hash1ihash2

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.

Chce listę identycznych kluczy, a nie liczbę identycznych kluczy. Myślę.
— Rosdi Kasim

Dzięki stefan za pomoc. Tak, Rosdi ma rację i ty też. Potrzebuję łącznej liczby podobnych wartości i podobnych wartości.
— user238384

1

Znalazłem bardzo podstawowy przykład porównania list na stronie Porównanie list. Ten przykład najpierw weryfikuje rozmiar, a następnie sprawdza dostępność określonego elementu jednej listy na innej.


-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
To rozwiązanie zwraca nieprawidłowy wynik, gdy dwa zawierają 3 kopie „jeden”. Dałoby to błędnie prawdziwy rezultat.
— Joseph Fitzgerald

Dzięki za tę część: && ls1.size () == ls2.size ()
— Nouar

1
Jakikolwiek powód, który Twoim zdaniem ? true :falsejest potrzebny w Twoim fragmencie?
— Krzysztof Tomaszewski
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.