こんにちは。たいら(@tairaengineer2)です。
今回の記事はJava8のラムダ式のmapToObjメソッドを使ってFizzBuzz問題を解く記事です。
スポンサーリンク
前提条件:eclipseの環境
この記事では、eclipseのバージョンは
バージョン | Eclipse4.7 Oxygen |
---|
を使っています。
インストールの仕方は、下の記事をご参考ください。
eclipseでのJavaプロジェクト作成方法は、以下の記事をご参考ください。
eclipseでのJavaファイル作成方法は、以下の記事をご参考ください。
FizzBuzz問題とは
3で割り切れる場合は「Fizz」(Bizz Buzzの場合は「Bizz」)、5で割り切れる場合は「Buzz」、両者で割り切れる場合(すなわち15で割り切れる場合)は「Fizz Buzz」(Bizz Buzzの場合は「Bizz Buzz」)を数の代わりに発言しなければならない。
Fizz Buzz - Wikipediaから引用させて頂きました
芸人の世界のナベアツさんのように、3の倍数のときは「Fizz」、5の倍数のときは「Buzz」、15の倍数のときは「Fizz Buzz」を表示させる問題です。
よくプログラム初心者の問題として使われます。
フォルダ構成
フォルダ構成は↓の通りです。
プログラムの概要
標準入力からFizzBuzzを表示するプログラムです。
今回Javaのプログラムを2つ作りました。
役割は
- FizzBuzz.java:FizzBuzzを表示する
- FizzBuzzMain.java:FizzBuzzのメイン
FizzBuzz.java
package fizzBuzz;
import java.util.stream.IntStream;
/**
* FizzBuzzを表示するクラス
*
*/
public class FizzBuzz {
/** 表示する範囲 */
private int scope = 0;
/** 定型文 */
public static final String FIZZ = "Fizz";
public static final String BUZZ = "Buzz";
public static final String SIZE_CHECK = "入力してください";
public static final String NUM_CHECK = "数字を入力してください";
/**
* 与えられた引数が数字かどうか判定
* @param args
* @return true:数字 , false:数字以外
*/
public boolean isArgs(String[] args) {
// 引数が与えられているか判定
if (args == null || args.length == 0) {
System.out.println(SIZE_CHECK);
return false;
}
// 0番目の引数が数字に変換できるかどうか判定
try {
this.scope = Integer.parseInt(args[0]);
} catch (NumberFormatException e) {
System.out.println(NUM_CHECK);
return false;
}
return true;
}
/**
* FizzBuzzを表示するメソッド
*/
public void printFizzBuzz() {
IntStream.rangeClosed(1, scope)
.mapToObj(e ->
(e % 15 == 0) ? FIZZ + BUZZ :
(e % 3 == 0) ? FIZZ :
(e % 5 == 0) ? BUZZ :
Integer.toString(e))
.forEach(e -> System.out.println(e));
}
}
FizzBuzzMain.java
package fizzBuzz;
/**
* FizzBuzzのメインクラス
*
*/
public class FizzBuzzMain {
public static void main(String[] args) {
FizzBuzz fizzBuzz = new FizzBuzz();
// 引数を判定
if(!fizzBuzz.isArgs(args)) {
return;
}
// FizzBuzzを表示
fizzBuzz.printFizzBuzz();
}
}
実行結果
では、実際に実行してみましょう!
以下の場合に沿って実行していきます。
- 何も設定しない場合
- 文字を引数に設定した場合
- 数字を設定した場合
何も設定しない場合
↓のように、何も入力しないで実行してみましょう。
入力してください
何も入力しないと、エラーメッセージが出ます!
文字を引数に設定した場合
↓のように、文字を入力して実行してみましょう。
数字を入力してください
文字だけの場合も、エラーメッセージが出ます!
数字を設定した場合
↓のように、数字を入力して実行してみましょう。
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz
16
想定通り、FizzBuzzを表示することができました!
スポンサーリンク
解説
以下の点を解説します。
- IntStreamとrangeClosedメソッドについて
- mapToObjメソッドの中の処理について
IntStreamとrangeClosedメソッドについて
順次および並列の集約操作をサポートするプリミティブint値要素のシーケンスです。
java.util.stream (Java Platform SE 8)から引用させて頂きました
IntStreamを使うと、プリミティブ型のint型のStreamを作ることができます。
そのIntStreamを使って、rangeClosedメソッドで与えられた引数の範囲内のIntStreamを作ります。
rangeClosed
static IntStream rangeClosed(int startInclusive,
int endInclusive)
startInclusive(含む)からendInclusive(含む)の範囲でステップ1でインクリメントした値を含む、順序付けされた順次IntStreamを返します。
IntStream (Java Platform SE 8)から引用させて頂きました
今回の場合だったら、1からscopeまでの連続したIntStreamを返してます。
mapToObjメソッドの中の処理について
そもそもmapToObjメソッドとは
mapToObj
<U> Stream<U> mapToObj(IntFunction<? extends U> mapper)
指定された関数をこのストリームの要素に適用した結果から構成される、オブジェクト値のStreamを返します。
これは中間操作です。
IntStream (Java Platform SE 8)
このメソッドを使うと、最初はint型のStreamだったとしても、今回のようにString型のStreamにすることができます。
IntStreamの各数字をmapToObjメソッドの中の処理で、場合分けして、文字列にしています。
.mapToObj(e ->
(e % 15 == 0) ? FIZZ + BUZZ :
(e % 3 == 0) ? FIZZ :
(e % 5 == 0) ? BUZZ :
Integer.toString(e))
上の処理は三項演算子の処理を長く書いているだけです。
三項演算子で書かない場合、↓の意味になります。
if (e % 15 == 0) {
FIZZ + BUZZ;
} else if (e % 3 == 0) {
FIZZ;
} else if (e % 5 == 0) {
BUZZ;
} else {
Integer.toString(e);
}
各数字を場合分けして、文字を返しているだけです。
スポンサーリンク
まとめ:FizzBuzz問題は初心者はぜひチャレンジしてみてください!
以上がラムダ式を使って、FizzBuzz問題を解いてみました。
少しでも、あなたの参考になれば幸いです。
ではでは~(・ω・)ノシ
ほかにも勉強記事を書いてます。
よければご参考ください。