2009-11-03 15 views
13

Proste pytanie.Porównaj dwie listy dla aktualizacji, usunięć i dodatków.

Mam nową listę i starą listę. Czy w Javie istnieje standardowa metoda/biblioteka, która pozwala mi porównywać te dwie listy i określać, które pozycje zostały zaktualizowane/usunięte lub są zupełnie nowe? Na przykład. Powinienem skończyć z trzema listami - Usunięte elementy (stare, ale nie nowe), Zaktualizowane elementy (przedmioty w obu), Nowe elementy (elementy w nowym, a nie w starym).

Mogłem napisać to sam, ale zastanawiałem się, czy istnieje standardowy sposób, aby to zrobić.

Obiekty na liście są równe poprawnie.

+0

Czy martwi Cię kolejność list? Na przykład sugerowane dotychczas rozwiązania obejmujące metodę retainAll/removeAll nie zajmą się sytuacją, w której nowa lista zawiera te same elementy co stara lista, aczkolwiek w innej kolejności; na przykład {"foo", "bar"} vs {"bar", "foo"}. – Adamski

+0

Dopóki metoda równości jest zaimplementowana poprawnie, nie widzę powodu, dla którego zamówienie powinno wpływać na removeAll itd. Na pewno nie sugeruje w javadoc: usuwa z tej listy wszystkie elementy, które są zawarte w określonej kolekcji (operacja opcjonalna). – Pablojim

Odpowiedz

31

Brak standardu przepraszam. Możesz to zrobić dość łatwo dzięki standardowemu JDK bez konieczności dodawania zależności od Apache Commons (jak sugerowali inni). Zakładając, że listy są List<T> przypadki:

List<T> oldList = ... 
List<T> newList= ... 

List<T> removed = new ArrayList<T>(oldList); 
removed.removeAll(newList); 

List<T> same = new ArrayList<T>(oldList); 
same.retainAll(newList); 

List<T> added = new ArrayList<T>(newList); 
added.removeAll(oldList); 
+0

+1 - tak, znacznie lepiej niż moje. –

+1

Niestety jest to nieco błędne ... removeAll i podobne działają na podanej liście i zwracają wartość boolowską. Więc to się nie skompiluje. Musi być: Lista added = new ArrayList (nowa lista); added.removeAll (oldList); itd ... Więc może być przypadek dla metod Apache commons, mimo wszystko ... – Pablojim

+0

@Pablojim: całkiem dobrze, dzięki. Naprawiony. – cletus

3

Chciałbym użyć Apache CollectionUtils i użyć unii (elementy w obu) i funkcji rozłącznych (zmienić kolejność, aby uzyskać jedną lub drugą).

Najlepiej byłoby zrobić jeden przejazd nad wszystkimi elementami zamiast 3, ale jeśli to nie jest wąskie gardło, nie martwiłbym się teraz o wydajność.

7

Nie ma nic w standardowych bibliotekach.

Jednak Apache Commons CollectionUtils klasa udostępnia taką funkcjonalność z punktu przecięcia i odejmować metody:

Collection<T> old = ...; 
Collection<T> neww = ...; 

Collection<T> deleted = (Collection<T>)CollectionUtils.subtract(old, new); 
Collection<T> updated = (Collection<T>)CollectionUtils.intersection(old, new); 
Collection<T> newResult = (Collection<T>)CollectionUtils.subtract(new, old); 

(Musisz (niezaznaczone) rzuca bo CollectionUtils nie generified.)

1

myślę, że można to osiągnąć z biblioteki standardowej java też. Spójrz na następujących metod java.util.Collection:

retainAll (Collection c)

Zachowuje tylko elementy w tej kolekcji, które są zawarte w określonej kolekcji (opcjonalnie pracy) . Innymi słowy, usuwa z tej kolekcji wszystkie jej elementy , które nie są zawarte w podanej kolekcji .

removeAll (Collection c)

Usuwa wszystkie elementy tej kolekcji jest które są również zawarte w określonej kolekcji (opcjonalnie operacji). Po zwróceniu tego połączenia, , ta kolekcja nie będzie zawierała elementów wspólnych dla określonej kolekcji .

0

Jeśli istnieje standardowy sposób, ja nie wiem ...
Spojrzałem na Collections ale widział tylko rozłączne() (to już informacja ...) i indexOfSubList() (nie wiem jeśli jest w ogóle użyteczny).
Spojrzałem również na Google Collections i jeśli nie ma podobnego obiektu, są tam przydatne narzędzia, takie jak funkcja filtru(), która może pomóc, jeśli utworzysz odpowiedni predykat.

[EDYTOWANIE] Tęskniłem za usunięciem i zachowanie wszystkich metod zbierania ... Nie usuwam tej odpowiedzi, nawet jeśli jest ona nieco żałosna, ponieważ jest w pewien sposób komplementarna z pozostałymi odpowiedziami ... (Myślę, że kolekcje Google jest przynajmniej wspomnieć!)

2

Osobiście uważam, że jedynym rozsądnym sposobem, aby wyjaśnić różnicę między dwoma list jest z pełnowymiarową algorytmu diff (takiego polecenia diff uNIX).

Zestawy są jednak znacznie prostsze. Kolekcje Google udostępniają metodę Sets.difference(Set, Set), a także związki i skrzyżowania.