#導入
こんにちは。けちょんです。
皆さん、stream使ってますか?
私は数日前に学んだのですが、めっちゃはまってます。
業務中も隙あらばいじってます。
今回はstreamを使ってFizzBuzzを出力してみます。
#やってみる
##なにはともあれ、1~100までを生成
IntStream.range(1,101);
rangeClosedではなく、rangeの理由はショートコードを意識しました。
(最終的にそんなに短くならない)
##mapToObjを使って、FizzBuzzを作成
IntStream.range(1,101).mapToObj(i->i%3==0&&i%5==0?"FizzBuzz":i%3==0?"Fizz":i%5==0?"Buzz":i).forEach(i->System.out.println(i));
はい、書いてて辛いし、きっと皆さんも辛い。
i->i%3==0&&i%5==0?"FizzBuzz":i%3==0?"Fizz":i%5==0?"Buzz":i
この部分でFizzBuzzを実装してます。
3項演算子で、以下の順に文字列に変換してます。
- 3でも5でも割り切れるならFizzBuzzに変換
- 3で割り切れるならFizzに変換
- 5で割り切れるならBuzzに変換
- そのまま
出力結果
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
17
Fizz
19
Buzz
Fizz
22
23
Fizz
Buzz
26
Fizz
28
29
FizzBuzz
・・・
よさげですね。
#短くしてみる
現在129byteですが、もう少し短くできますね。
##メソッド参照を使う
メソッド参照を使うと、引数を省略できます。
i->System.out.println(i)
をSystem.out::println
と表記できます。
IntStream.range(1,101).mapToObj(i->(i%3==0&&i%5==0)?"FizzBuzz":i%3==0?"Fizz":i%5==0?"Buzz":i).forEach(System.out::println);
これで124byteです
##==を>で書く
その方が一文字短いですね。
IntStream.range(1,101).mapToObj(i->(i%3>0&&i%5>0)?i:i%3>0?"Buzz":i%5>0?"Fizz":"FizzBuzz").forEach(System.out::println);
これで120byteになりました。
さらに短くする方法を募集中です
#まとめ
stream楽しい
#追記
コメント欄にてより短いコードを書いてくださりました。
IntStream.range(1,101).forEach(i->System.out.println((i%3<1?"Fizz":"")+(i%5<1?"Buzz":i%3<1?"":i)));
FizzBuzzの文字列の冗長さを取り除いています。
mapToObjを使わず、そのまま出力。
なんと100byte!!