LoginSignup
10
8

More than 5 years have passed since last update.

フィボナッチ数のStreamを作成する

Last updated at Posted at 2016-03-03

フィボナッチ数をStreamで扱ってみました。

サンプル

import java.math.BigInteger;
import java.util.stream.Stream;

/**
 * フィボナッチ数をストリームで生成するサンプル
 */
public class Fibonacci {

    /**
     * 1000以上のフィボナッチ数を5件出力する。
     * 
     * @param args
     */
    public static void main(String[] args) {
        fibonacciStream()
            .filter(n -> n.compareTo(BigInteger.valueOf(1000l)) >= 0)
            .limit(5l)
            .forEach(System.out::println);
    }

    /**
     * フィボナッチ数列のストリームを返す。
     * 
     * @return フィボナッチ数列のストリーム
     */
    public static Stream<BigInteger> fibonacciStream() {
        return Stream.iterate(
                    new BigInteger[]{BigInteger.valueOf(1l), BigInteger.valueOf(1l)},
                    n -> {
                        BigInteger tmp = n[1];
                        n[1] = n[0].add(n[1]);
                        n[0] = tmp;
                        return n;
                    }
                )
                .map(n -> n[1])
                ;
    }

}

解説

少しだけ解説します。

フィボナッチ数列

0, 1を起点に1, 2, 3, 5, 8, 13, 21, 34 …のように1つ前と2つ前の数値を合算したものが続いていく数列です。

Streamを使用せずに実装(whileループ)

int num1 = 0;
int num2 = 1;
int cnt = 0;
List<Integer> list = new ArrayList<Integer>();
while (++cnt <= 10) {
    int tmp = num2;
    num2 = num1 + num2;
    num1 = tmp;
    list.add(Integer.valueOf(num2));
}
System.out.println(list.toString());

// 出力結果は以下のとおり
// [1, 2, 3, 5, 8, 13, 21, 34, 55, 89]

Streamを使用して実装

無限ストリームを作成

Stream
    .iterate(
        new BigInteger[]{BigInteger.valueOf(1l), BigInteger.valueOf(1l)},
        n -> {
            BigInteger tmp = n[1];
            n[1] = n[0].add(n[1]);
            n[0] = tmp;
            return n;
        }
    )
    .map(n -> n[1])
    ;

iterateで無限ストリームを生成できます。
1つめのメソッドパラメータは最初の要素です。
2つめのメソッドパラメータは前の要素を元に新しい要素を返すための関数になります。

mapでBigInteger配列のフィボナッチ数を持つ要素のみ返すようにしています。

フィルタ、リミット、結果出力

Stream.iterate(
        new BigInteger[]{BigInteger.valueOf(1l), BigInteger.valueOf(1l)},
        n -> {
            BigInteger tmp = n[1];
            n[1] = n[0].add(n[1]);
            n[0] = tmp;
            return n;
        }
    )
    .map(n -> n[1])
    .filter(n -> n.compareTo(BigInteger.valueOf(1000)) > 0)
    .limit(5)
    .forEach(System.out::println);

filterで条件を指定し、limitで制限掛けて、forEachでSystem.out.printlnを実行して出力しています。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8