2012-01-17 25 views
7

Mam dwie klasy Pojo na różnych polach z unikalnym identyfikatorem.przecięcie dwóch list różnych obiektów w java

Chcę wykonać przecięcie dwóch List<A> i List<B>.

Co najlepiej zrobić. Jednym z nich jest to, że mogę po prostu iterować dwa razy, ale wtedy złożoność jest zbyt wysoka n2.

to lepszy sposób na zrobienie tego? Czy mogę to zrobić za pomocą Komparatora?

Class A { 
Id, Name ,DOB} 

Class B{ 
id, aid ,location } 

Mam wykaz A, Lista B

teraz chcą uzyskać listę A z umieszczeniem w B

+0

możliwe duplikat [Czy istnieje sposób, aby obliczyć przecięcie dwóch zestawów?] (Http: // stackoverflow .com/questions/8882097/is-there-a-way-to-calcul-the-cross-of-two-sets) – Bohemian

+0

Czy Twoje listy są posortowane (na id/Id)? –

+1

@Bohemian, 'Set' i' List' nie są identyczne. – Paul

Odpowiedz

3

Apache Commons kolekcje ma sposobu, aby to zrobić: CollectionUtils.intersection. Nie używa jednak generycznych leków.

Jest też ten SO pytanie: List intersection in java

+0

Należy zauważyć, że CollectionUtils.intersection nie daje żadnych gwarancji co do kolejności pozycji w wyniku (jego typem powrotu jest kolekcja). Ponieważ masz do czynienia z Listami, miej to na uwadze. – NBJack

+0

Jeśli zamówienie jest ważne, należy wypróbować ListUtils.intersection. – NBJack

2

Można umieścić elementy List<B> do HashMap<Integer,B>, z id jest kluczem.

Po wykonaniu tej czynności można powtórzyć elementy List<A> i szybko wyszukać odpowiednie elementy B za pomocą mapy skrótów. To zapewni wymaganą strukturę ("lista A z lokalizacją w B").

+0

-1 Musisz żartować.* Naprawdę * nędzne rozwiązanie, ale jeśli musisz tak postąpić, użyj 'Set', a nie' Map' (używasz tylko zestawu kluczy z mapy - czy to wydaje się znajome .. keySET? ... * * SET **?) Geez ... – Bohemian

+1

@Bohemian: Wyraźnie masz na myśli inne rozwiązanie. Dlaczego nie chcesz go opublikować jako odpowiedzi? – NPE

+1

Uczciwe wyzwanie - napisałem rozwiązanie. To był koniec długiego dnia - przepraszam za "akt. Mógłbym to powiedzieć milej. Wciąż jest jednak prawdą, że "mapa" jest niewłaściwym narzędziem. – Bohemian

2
  1. Sortuj listę w kolejności rosnącej Id.

  2. start z listy A, i znaleźć odpowiedni indeks w wykazie B. Pamiętaj aktualny spis wykazie B. powiedzieć (INDB)

  3. start z kolejnym indeksem wykazie A, i porównać w wykazie B, wychodząc z (indB + 1)

  4. Powtarzaj czynności od 1 do 4, aż do zakończenia listy A LUB zakończenia listy B.

1

Spróbuj tego:

public static void main(String[] args) {System.nanoTime() 
    List<A> as = new ArrayList<A>(); 
    List<B> bs = new ArrayList<B>(); 

    // Collect all A.ids in the list of B into a Set 
    Set<String> baids = new HashSet<String>(); 
    for (B b : bs) 
     baids.add(b.aid); 

    // iterate through the list of A discarding those that don't have a B 
    for (Iterator<A> i = as.iterator(); i.hasNext();) 
     if (!baids.contains(i.next().Id)) // contains() executes fast for a Set 
      i.remove(); 

    // now list "as" contains all A that have a B with A.Id = B.aid 
} 
+0

Wymagane dane wyjściowe to * "lista A z lokalizacją w B" *. W jaki sposób osiąga to algorytm? – NPE

+0

ale potem robię pierwszą pętlę dla get-id z jednej listy, drugą dla otrzymania pętli z drugiej listy i wewnętrznie zachowuję wszystko również dla pętli, a potem uruchomię jeszcze jedną pętlę dla uzyskania dokładnego obiektu. Czy to możliwe, że możemy zrobić, używając obiektu i przesłonić równe? –

+0

@ aix (uważa, że ​​omg ... muszę łyżeczkować?) Dobrze ... Dodałem jeszcze jedną linię, aby pokazać, jak rozwiązuje się zagadkę pozyskiwania listy z zestawu. – Bohemian

0

Korzystanie Java 8 strumieni

List<A> listA = new ArrayList<A>(); 
List<B> listB = new ArrayList<B>(); 

Set<Integer> aIdsFromBList = listB.stream().map(B::getAId).collect(Collectors.toSet()); 

return listA.stream 
    .filter(a -> aIdsFromBList.contains(a.getId())) 
    .collect(Collectors.toList());