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.