web-dev-qa-db-ja.com

ストリームを使用して、2つのリストまたは配列の乗算から要素のペアを見つける方法

番号のリストが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]+ "}");
    });
}
20
Ankur Singh

map()の代わりにflatMap()メソッドを使用すると、結合されますストリームを1つに。参照: map()とflatMap() の違いと flatMap()の例

15
Rohit Gulati

最初のmap()flatMap() に置き換える必要があります。

14
JB Nizet

これは、List<Integer>の代わりに2つのIntStream配列をソースとして使用するintを使用するソリューションです。すべてのintIntegerとしてボックス化せずにこの問題を解決できるかどうかを確認したかったのです。

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を返すためIntStreamIntStreamを使用できませんでした。現在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メソッドがあります。これは基本的に、flatMapToObjIntStreamメソッドが実行する必要があることを実行します。

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ソリューションはスレッドセーフではなく、IntStreamparallelの場合は壊れます。次のソリューションは、シリアルまたはパラレルで機能するはずです。 mapToObjIntStreamを実行し、その後に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コレクション のコミッターです。

14
Donald Raab
//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);
0
Sadaf Najam

この特定のケースでは、flatMapを使用して、配列の作成をバイパスし、次のようにコードを単純化することもできます。

list1.stream()
     .flatMap(i -> list2.stream().map(j -> "{" + i+ "," + j + "}"))
     .forEach(System.out::println);
0
Tagir Valeev