2016-02-19 15 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

あなたは要素がevensに存在しないことを保証Predicateを渡し、Stream's filter methodを使用することができます。

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

あなたは、いくつかのソリューションがあります

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

大きなevenリストに

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

またはより効率的に使用することができます。

まず、ストリームを使用せずに、あなただけの新しいリストを作成することができますし、それから、別のコレクションからすべての要素を削除...

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

(あなたがこのケースでevensSetを行うことを検討する必要があります)。

最後に、上記のロジックを変更して、すべての偶数のコレクションではなく、 "evens"を関数として表すことができます。これは基本的に上記と同じですが、2番目のコレクションを持つ必要はありません。

final List<Integer> others3 = multiplesOfThree 
    .stream() 
    .filter(x -> x % 2 != 0) 
    .collect(Collectors.toList()); 
関連する問題