2016-05-30 3 views
13

私はCollectionの任意のクラスの要素を持っています。コレクションを繰り返し処理し、コレクションの要素と他の要素を1つずつ(要素自体を除いて)使用して、何らかの操作を実行したいとします。それは簡単にするためにList<Integer>なりましょう:forJava 8ストリーム:リストの可能なすべての要素のペアを処理します

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

は、それがされるループ:

for (Integer i : list) { 
    for (Integer j : list) { 
     if (!i.equals(j)) System.out.println(i * 2 + j); //just for example 
    } 
} 

質問がStream APIでそれを行うにはどのようにのですか?それはしかし、ネストされたループよりも優れて見えない

list.stream().forEach(i -> 
    list.stream().forEach(j -> { 
     if (!i.equals(j)) System.out.println(i * 2 + j); 
    }) 
); 

:私はになってきたものだ

。よりエレガントな方法がありますか?

答えて

13

あなたがflatMap操作を使用してこれを行うことができます。このコードは、入力リストのストリームを作成している

list.stream() 
    .flatMap(i -> list.stream().filter(j -> !i.equals(j)).map(j -> i * 2 + j)) 
    .forEach(System.out::println); 

。これは、リストの各要素を、現在の要素が除外された同じリストによって作成されたストリームでマップし、この新しいリストの各要素は、i * 2 + j操作の結果です。

すべての要素がコンソールに出力されます。

6

intの値に事前にマッピングすることで、オブジェクトの比較を避けることができます。

list.stream().mapToInt(Integer::intValue) 
    .flatMap(i -> list.stream().filter(j -> j!=i).mapToInt(j -> i*2 + j)) 
    .forEach(System.out::println); 

実際には、条件付き演算と不変のものの等式チェックを実行しています。全体の動作の間に、その内容を変更しないソースリストに依存しているとして、あなたは、単に最初の場所でペアリングリストのインデックスを生成することができます:

は場合
final int end=list.size(); 
IntStream.range(0, end).flatMap(i -> 
    IntStream.concat(IntStream.range(0, i), IntStream.range(i+1, end)) 
     .map(j -> list.get(i) * 2 + list.get(j))) 
    .forEach(System.out::println); 

あなたは数値を計算する必要はありませんが、 IntStreamにはflatMapToObjという操作がないため、さらに複雑になります。mapToObjflatMapの組み合わせが必要です(boxedを使用しない限り)。 Listに対処せず、[ 1, 2, 3, 4, 5 ]ような単純なリスト、私たちは最初の場所でIntStream.rangeClosed(1, 5)を使用する可能性があるため、当然のことながら

IntStream.range(0, end).mapToObj(i -> 
    IntStream.concat(IntStream.range(0, i), IntStream.range(i+1, end)) 
     .mapToObj(j -> new int[]{ list.get(i), list.get(j)})) 
     .flatMap(Function.identity()) 
    .forEach(a -> System.out.println(a[0]*2+a[1])); 

::だから2の長さの配列の一例を構築することのように見えます

IntStream.rangeClosed(1, 5).flatMap(i -> 
     IntStream.concat(IntStream.range(1, i), IntStream.rangeClosed(i+1, 5)) 
     .map(j -> i*2 + j)) 
    .forEach(System.out::println); 
関連する問題