W Javie 8 ze strumieniami jest to całkiem proste. EDYCJA: Może być wydajna bez strumieni, patrz niżej.
List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21");
List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19",
"2009-05-20","2009-05-21","2009-05-21","2009-05-22");
List<String> result = listB.stream()
.filter(not(new HashSet<>(listA)::contains))
.collect(Collectors.toList());
Zwróć uwagę, że zestaw skrótów jest tworzony tylko raz: odwołanie do metody jest powiązane z metodą zawierającą. Zrobienie tego samego z lambdą wymagałoby posiadania zestawu w zmiennej. Tworzenie zmiennej nie jest złym pomysłem, zwłaszcza jeśli uznasz to za brzydkie lub trudniejsze do zrozumienia.
Nie możesz łatwo zanegować predykatu bez czegoś takiego jak ta metoda narzędziowa (lub jawne rzutowanie), ponieważ nie możesz bezpośrednio wywołać odwołania do metody negacji (najpierw wymagane jest wnioskowanie o typie).
private static <T> Predicate<T> not(Predicate<T> predicate) {
return predicate.negate();
}
Gdyby strumienie miały jakąś filterOut
metodę lub coś, wyglądałoby to ładniej.
Również @Holger dał mi pomysł. ArrayList
ma swoją removeAll
metodę zoptymalizowaną pod kątem wielokrotnych usunięć, zmienia układ elementów tylko raz. Jednak używa contains
metody dostarczonej przez daną kolekcję, więc musimy zoptymalizować tę część, jeśli nie listA
jest mała.
Z listA
i listB
oświadczył wcześniej, to rozwiązanie nie wymaga Javy 8 i jest bardzo wydajny.
List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));