2016-02-19 59 views
9

我很感興趣的是確定一種方法,返回元素列表中不包含另一個列表中的元素。Java 8流。所有元素除了其他元素

例如

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 

你怎麼做到這一點? 我發現這是一個有點笨重,難以閱讀的方法....

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

回答

12

您可以使用Stream's filter method,傳遞Predicate,以確保該元素不存在evens

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

但是假設你有一個可變的List(例如ArrayList),你甚至不需要流,只是Collections's removeAll method

multiplesOfThree.removeAll(evens); 
+0

removeAll是一個優秀的解決方案。 –

5

你可以使用

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

或大even名單

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

有幾個解決方案更有效。

首先,不使用流,你可以創建一個新的列表,並從它的另一個集合中刪除的所有元素...

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); 

另一個解決方案是通過一個過濾器,通過流():

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

(您可能需要考慮使evens在這種情況下Set)。

最後,你可以修改上面的邏輯來表示「evens」作爲一個函數,而不是所有偶數的集合。這與上述基本相同,但您不必擁有第二個集合。

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