2017-05-04 24 views
5

Java 8のStreamsでは、述語に基づいてコレクションをフィルタリングし、述語が真であったアイテムを処理する方法を知っています。私が思っているのは、述語がコレクションを2つのグループに分ける場合、APIを使用して述語に基づいてフィルタリングし、フィルタリングされた結果を処理し、直ちに呼び出しを連鎖させてフィルタによって除外されるすべての要素?例えばJava 8 Stream:フィルタ処理、結果処理、除外処理

、以下のリストを検討してください。

List<Integer> intList = Arrays.asList(1,2,3,4); 

を行うことが可能です:

intList.stream() 
    .filter(lessThanThree -> lessThanThree < 3) 
    .forEach(/* process */) 
    .exclusions(/* process exclusions */); //<-- obviously sudocode 

または私はちょうどフィルターの項目についてforEachプロセスを行い、その後、stream()を呼び出す必要があります元のリストにfilter()を入力して残りのアイテムを処理しますか?

ありがとうございます!

+4

https://stackoverflow.com/q/43766534/2711488 – Holger

答えて

8

述語を引数として受け取るCollectors.partitioningByを見てください。使用するにはStream.collectを使用する必要があります。

結果は2つだけBooleanエントリを持つマップです:trueキーのために、あなたはfalseキーのために、あなたはdidnの要素を含むListを持っていながら、述語にマッチしたストリームの要素を含むListを持っていますマッチしない。

には、各パーティションをリストとは別のものに収集する場合に使用できるダウンストリームコレクタである第2引数を受け入れるオーバーロードされたバージョンがあります。あなたの例では

、あなたはそれをこのように使用することができます

Map<Boolean, List<Integer>> partition = intList.stream() 
    .collect(Collectors.partitioningBy(i -> i < 3)); 

List<Integer> lessThan = partition.get(true); // [1, 2] 
List<Integer> notLessThan = partition.get(false); // [3, 4] 

を私もリンクされ、問題のユーザー@Holgerで追加したコメントから取られ、重要な観察を強調したいと思います:

Collectors.partitioningByは、Mapには常にtruefalseの結果があります。つまり、そのグループに要素が含まれていない場合は空のリストで、nullではなくなります。

この特殊性は、(再び、これはユーザ@Holgerにより観察された)API注としてjdk9 docsに追加されました:

パーティションに要素がない場合、結果のマップでその値がされます空のリスト

+2

サンプルはhttp://www.concretepageから入手できます。com/java/jdk-8/java-8-collectors-partitioningby-example –

1

除外されたアイテムにアクセスするための操作はStreamインターフェイスにはありません。ただし、より複雑な述語を実装することもできます。

intList.stream() 
    .filter(i -> { 
     if (i < 3) return true; 
     else { 
      // Process excluded item i 
      return false; 
     } 
    }).forEach(/* Process included item. */) 

ただし、述語を非干渉的にステートレスに保つように注意する必要があります。