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ąś filterOutmetodę lub coś, wyglądałoby to ładniej.
Również @Holger dał mi pomysł. ArrayListma swoją removeAllmetodę zoptymalizowaną pod kątem wielokrotnych usunięć, zmienia układ elementów tylko raz. Jednak używa containsmetody dostarczonej przez daną kolekcję, więc musimy zoptymalizować tę część, jeśli nie listAjest mała.
Z listAi listBoś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));