番号のリストが2つあり、可能なすべての番号のペアを見つけたいと思います。たとえば、リスト[1、2、3]および[3、4]が与えられた場合、結果は[(1、3)、(1、4)、(2、3)、(2、4)、(3 、3)、(3、4)]。
for
ループを使用してこれを実行できることはわかっていますが、Java 8ストリームを使用してこれを実行するためのより簡潔な方法はありますか?
次のことを試しましたが、List<Stream<int[]>>
ではなくList<int[]>
を取得しているため、何かが足りません。
public static void main(String[] args) {
List<Integer> list1 = Arrays.asList(1, 2, 3);
List<Integer> list2 = Arrays.asList(3, 4);
List<int[]> pairs = list1.stream().map(i -> list2.stream().map(j -> new int[] { i, j }))
.collect(Collectors.toList());
pairs.forEach(i -> {
System.out.println("{" + i[0]+ "," + i[1]+ "}");
});
}
map()の代わりにflatMap()メソッドを使用すると、結合されますストリームを1つに。参照: map()とflatMap() の違いと flatMap()の例
最初のmap()
を flatMap()
に置き換える必要があります。
これは、List<Integer>
の代わりに2つのIntStream
配列をソースとして使用するint
を使用するソリューションです。すべてのint
をInteger
としてボックス化せずにこの問題を解決できるかどうかを確認したかったのです。
int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<IntIntPair> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
IntStream.of(two).mapToObj(j -> PrimitiveTuples.pair(i, j)).forEach(list::add));
System.out.println(list);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
残念ながら、flatMap
を返すためIntStream
でIntStream
を使用できませんでした。現在flatMapToObj
にはIntStream
はありません。これは、ここで必要になるものです。そこで、代わりにforEach
を使用しました。
IntIntPair
および PrimitiveTuples
私が Eclipse Collections から使用したクラスは、リストを文字列として出力するのが簡単になったためです。ソリューションと同じようにint[]
を使用できます。コードは次のようになります。
List<int[]> list = new ArrayList<>();
IntStream.of(one).forEach(i ->
IntStream.of(two).mapToObj(j -> new int[]{i, j}).forEach(list::add));
Eclipseコレクションの8.1リリース(3月中旬にリリース予定)では、この問題を解決するために使用できるライブラリ内のすべてのプリミティブコンテナにflatCollect
メソッドがあります。これは基本的に、flatMapToObj
のIntStream
メソッドが実行する必要があることを実行します。
IntList a = IntLists.mutable.with(1, 2, 3);
IntList b = IntLists.mutable.with(3, 4);
List<IntIntPair> result =
a.flatCollect(
i -> b.collect(j -> PrimitiveTuples.pair(i, j)),
Lists.mutable.empty());
System.out.println(result);
// [1:3, 1:4, 2:3, 2:4, 3:3, 3:4]
更新:
Boris the Spiderのコメントで指摘されているように、forEach
ソリューションはスレッドセーフではなく、IntStream
がparallel
の場合は壊れます。次のソリューションは、シリアルまたはパラレルで機能するはずです。 mapToObj
でIntStream
を実行し、その後にflatMap
を実行することを考えていなかったので、これが指摘されてよかったです。
int[] one = new int[]{1, 2, 3};
int[] two = new int[]{3, 4};
List<int[]> list = IntStream.of(one).parallel()
.mapToObj(i -> IntStream.of(two).mapToObj(j -> new int[]{i, j}))
.flatMap(e -> e)
.collect(Collectors.toList());
list.stream().map(e -> "{" + e[0] + "," + e[1] + "}").forEach(System.out::println);
注:私は Eclipseコレクション のコミッターです。
//return pair of numbers
List<List<Integer>> pairs=numbers.stream()
.flatMap(i -> numbers2.stream()
.map(j -> Arrays.asList(i,j)))
.collect(Collectors.toList());
pairs.stream().forEach(System.out::println);
この特定のケースでは、flatMap
を使用して、配列の作成をバイパスし、次のようにコードを単純化することもできます。
list1.stream()
.flatMap(i -> list2.stream().map(j -> "{" + i+ "," + j + "}"))
.forEach(System.out::println);