Observableにして無限リスト的に好きなだけ生成出来る!と思ったんだけど、
Fibonacci.java
public class Fibonacci { public static Observable<Integer> take(int count) { if (count == 0) { return Observable.empty(); } if (count == 1) { return Observable.just(1); } return Observable.from(new Integer[]{1, 1}) .concatWith(Observable.zip( take(count - 1), take(count - 1).skip(1), (i1, i2) -> i1 + i2)); } }
usage
Fibonacci.take(0) .subscribe(i -> Log.d("Fibonacci", Integer.toString(i))); // empty Fibonacci.take(1) .subscribe(i -> Log.d("Fibonacci", Integer.toString(i))); // 1 Fibonacci.take(2) .subscribe(i -> Log.d("Fibonacci", Integer.toString(i))); // 1, 1 Fibonacci.take(10) .subscribe(i -> Log.d("Fibonacci", Integer.toString(i))); // 1, 1, 2, 3, 5, 8, 13, 21, 34, 55
ところが
Fibonacci.take(15)
とかで計算が爆発して死ぬ。つらい。
仕方ないので
こういう面白みのない感じに。
public class Fibonacci { static Map<Integer, Integer> FIBONACCI = new HashMap<>(); static { FIBONACCI.put(0, 1); FIBONACCI.put(1, 1); } public static Observable<Integer> take(int count) { if (count == 0) { return Observable.empty(); } return Observable.range(0, count) .map(i -> { if (FIBONACCI.containsKey(i)) { return FIBONACCI.get(i); } int result = FIBONACCI.get(i - 2) + FIBONACCI.get(i - 1); FIBONACCI.put(i, result); return result; }); } }
ただObservable化するとこういう実装も簡単にできて良い。
public static int at(int index) { return take(index).last().toBlocking().single(); }
まとめ
なんかもっといい感じの書き方ないかな