2016-02-19 17 views
9

Interesuje mnie identyfikacja podejścia, które zwraca listę elementów z wyłączeniem elementów z innej listy.Strumień Java 8. wszystkie elementy Z WYJĄTKIEM innych elementów

np

List<Integer> multiplesOfThree = ... // 3,6,9,12 etc 
List<Integer> evens = ... // 2,4,6,8 etc 
List<Integer> others = multiplesOfThree.except(evens) // should return a list of elements that are not in the other list 

w jaki sposób to zrobić? znalazłem podejście, które jest trochę niezgrabne i trudne do odczytania ....

multiplesOfThree.stream() 
.filter(intval -> evens.stream().noneMatch(even -> even.intValue() == intval.intValue())) 

Odpowiedz

12

Można użyć Stream's filter method, przekazując Predicate, który zapewnia, że ​​element nie istnieje w evens.

List<Integer> others = multiplesOfThree.stream() 
     .filter(i -> !evens.contains(i)) 
     .collect(Collectors.toList()); 

Ale zakładając, że mają zmienny List (np ArrayList), nie trzeba nawet strumienie, po prostu Collections's removeAll method.

multiplesOfThree.removeAll(evens); 
+0

removeAll to doskonałe rozwiązanie. –

5

Można użyć

multipleOfThree.stream() 
       .filter(((Predicate<Integer>) evens::contains).negate()) 

lub bardziej wydajne dla dużych even list

HashSet<Integer> evenSet = new HashSet<>(even); 
multipleOfThree.stream() 
       .filter(((Predicate<Integer>) evenSet::contains).negate()) 
1

Istnieje kilka rozwiązań.

Po pierwsze, bez korzystania ze strumieni, można po prostu stworzyć nową listę i usunąć wszystkie elementy z innej kolekcji z niego ...

final List<Integer> multiplesOfThree = Arrays.asList(3,6,9,12); 
final List<Integer> evens = Arrays.asList(2,4,6,8,10,12); 
final List<Integer> others1 = new ArrayList<>(multiplesOfThree); 
others1.removeAll(evens); 

Innym rozwiązaniem byłoby, aby przejść strumienia przez filtr():

final List<Integer> others2 = multiplesOfThree 
    .stream() 
    .filter(x -> !evens.contains(x)) 
    .collect(Collectors.toList()); 

(Możesz rozważyć evensSet w tym przypadku).

I na koniec można zmodyfikować powyższą logikę, aby przedstawić "evens" jako funkcję, a nie zbiór wszystkich liczb parzystych. Jest to zasadniczo takie samo, jak powyżej, ale nie musisz mieć drugiej kolekcji.

final List<Integer> others3 = multiplesOfThree 
    .stream() 
    .filter(x -> x % 2 != 0) 
    .collect(Collectors.toList()); 
Powiązane problemy