web-dev-qa-db-ja.com

Java 8 / lambdaを使用してネストされた 'if'ステートメントを実行する方法

次のコードがあり、楽しみのためにラムダ関数を使用して実装したいと思います。基本的な集計操作を使用して実行できますか?

List<Integer> result = new ArrayList<>();

for (int i = 1; i <= 10; i++) {
    if (10 % i == 0) {
        result.add(i);
        if (i != 5) {
            result.add(10 / i);
        }
    }
}

ラムダを使用:

List<Integer> result = IntStream.rangeClosed(1, 10)
                                .boxed()
                                .filter(i -> 10 % i == 0)
                                // a map or forEach function here?
                                // .map(return 10 / i -> if i != 5)
                                .collect(Collectors.toList());
21
LuckyGuess

ここでの本質的な観察は、あなたの問題は非同型変換を伴うということです:単一の入力要素は0、1、または2つの出力要素にマッピングできます。これに気づいたときはいつでも、flatMapの代わりにmapを含む解決策を探し始める必要があります。これがそのような一般的な変換を達成する唯一の方法だからです。特定のケースでは、最初に1対0の要素マッピングにfilterを適用し、次に1対2のマッピングにflatMapを適用できます。

List<Integer> result =
    IntStream.rangeClosed(1, 10)
             .filter(i -> 10 % i == 0)
             .flatMap(i -> i == 5 ? IntStream.of(i) : IntStream.of(i, 10 / i))
             .boxed()
             .collect(toList());
47
Marko Topolnik

ラムダの本体を宣言できます。例えば:

Runnable run = () -> System.out.println("Hey");

になり得る

Runnable run = () -> {
    System.out.println("Hey");
};

その本体内で、ネストされたステートメントを作成できます。

Runnable run = () -> {
    int num = 5;

    if(num == 5) {
        System.out.println("Hey");
    }
};
5
Vince Emigh

パイプラインまたは1対多マッピングに要素を追加しようとしているときに、flatMapを使用します。マップは1対1のマッピングです。

ArrayList<Integer> result = (ArrayList<Integer>) IntStream.rangeClosed(1, 10)
                .boxed()
                .filter(i -> 10 % i == 0)
                .flatMap((Integer i) -> {return i!=5 ? Stream.of(i, (10/i)):Stream.of(i);})
                .collect(Collectors.toList());

これにより、同じリストが作成されます

ArrayList<Integer> result2 = new ArrayList<Integer>();

        for (int i = 1; i <= 10; i++) {
            if (10 % i == 0) {
                result2.add(i);
                if (i != 5) {
                    result2.add(10 / i);
                }
            }
        }

どちらの方法が速いか疑問に思う場合、ループ方法はストリームを使用するよりも約3倍高速です。

Benchmark                     Mode  Cnt      Score     Error  Units
testStreams.Bench.loops       avgt    5     75.221 ±   0.576  ns/op
testStreams.Bench.streams     avgt    5    257.713 ±  13.125  ns/op
3
Mantis

あなたはこれを行うことができます:

List<Integer> result1 = IntStream
    .rangeClosed(1, 10)
    .boxed()
    .filter(i -> 10 % i == 0)
    .map(i -> (i != 5 ? Stream.of(i, 10 / i) : Stream.of(i)))
    .flatMap(Function.identity())
    .collect(Collectors.toList());
1
Mrinal

flatMapを使用してみてください:

List<Integer> result = IntStream.rangeClosed(1, 10)
        .boxed()
        .flatMap((i) -> {
            List<Integer> results = new ArrayList<>();
            if (10 % i == 0) {
                results.add(i);
                if (i != 5) {
                    results.add(10 / i);
                }
            }
            return results.stream();
        })
        .collect(Collectors.toList());

http://ideone.com/EOBiEP を参照してください

0
Danil Gaponov