Open4
長さが変わるストリーム処理を書きたい
intNumberStreamからevenNumberStreamを作るとか、(長さが半分になる)
BinaryStreamからBase32Streamを作るとか、(5バイトもらって8バイト吐くので長さが1.6倍になる)
どう実装したらいいかと考えている。
Array#map(fn)を使えばよいのになんとなくArray#reduce(fn, [])を使って後からなんでreduce とか書いてるんだ?と不思議になることがある。
これがヒントになった。
reduceのInitialにEmptyStreamを渡せばいいのかな。試す。
配列なら確認できた。
// javascript
[1,5,8,4,3,1,5,6].reduce(
function (prev, curr) {
if(prev.amount + curr > 10) { // 次の荷物を積んだら積載超過になる場合
prev.result.push(prev.amount); // 今のトラックは送り出して
prev.amount = 0; // 空のトラックを用意する
}
prev.amount += curr;
return prev;
},
{result:[], amount: 0}
).result
// => [6, 8, 8, 5]
Javaの Stream.reduce は、上流と同じ型を返すか、下流の型の Combiner を書かないといけない。
原則として Parallel Stream を想定していて、長さが変わるStreamを書くのは難しそう。
二つのStreamを橋渡ししてやればいいのか? と実装してみたんだけど、止まらなくなっちゃった。
// java
IntStream.Builder b = IntStream.builder();
IntStream s = IntStream.iterate(0, n -> n+1); // infinite stream
s.forEach(i -> b.add(i)); // 止まらない……
b.build().limit(100).forEach(System.out::println);
こういう感じか?
// java
Iterator<Integer> s = new Iterator<Integer>() {
int index = 0;
public Integer next() { return index++; }
public boolean hasNext() { return true; }
};
Iterator<Integer> r = new Iterator<Integer>() {
public Integer next() { return s.next(); }
public boolean hasNext() { return s.hasNext(); }
};
for(int i: (Iterable<Integer>)() -> r) {
if(i>100) break;
System.out.println(i);
}