limit と skip
上位 5 件が見たいだけなのに、全部出てくる
売上ランキングの上位 5 件だけ表示したい、というのはよくある要求です。for で書くと、カウンタを 1 つ増やして、途中で break することになります。
Java
int i = 0;
for (String row : ranking) {
System.out.println(row);
i++;
if (i == 5) break;
}表示したいのは 5 行なのに、行数を数える変数と、抜ける条件が別々に必要です。limit(5) を使えば、この 2 つが 1 つになります。
Java
List<String> top5 = ranking.stream().limit(5).toList();limit(n) は先頭から n 件通したところで、流すのをやめます。残りは読みにも行きません。件数が足りないときも例外は出ません。3 件しか無いところに limit(10) を書けば、あるだけの 3 件が返ります。
skip は逆に、先頭を捨てる
skip(n) は反対で、先頭の n 件を捨てて、それ以降を通します。CSV の 1 行目にヘッダが入っているときに便利です。
Java
List<String> body = lines.stream().skip(1).toList();こちらも、n が要素数より大きいときに例外は出ません。全部飛ばされて、空のまま次に進みます。
順番を入れ替えると、別の結果になる
limit と skip はどちらも中間操作なので、つなげて書けます。ただし書く順番で結果が変わります。
skip(1).limit(2) は、まず先頭 1 件を捨ててから、残った中の先頭 2 件を通します。手元に 5 件あるなら、2 件目と 3 件目が残ります。
limit(2).skip(1) は、まず先頭 2 件だけに絞ってから、その中の先頭 1 件を捨てます。残るのは 2 件目だけです。
同じ 2 つのメソッドを同じ引数で呼んでいるのに、結果は 2 件と 1 件で違います。「捨ててから取る」なのか「取ってから捨てる」なのかを、書く前に日本語で言えるようにしておくと間違えません。
件数が足りないときに例外を投げてくれないのは、便利な反面わなでもあります。
skip(10)を書いたのに空が返ってくるときは、元データが 10 件に届いていないことを疑ってください。
やってみよう
Solution.windowSum(int[] arr) を完成させて、配列の 3 件目から 5 件目までの合計を返してください。
ファイルの先頭に import java.util.stream.IntStream; を書き、IntStream.of(arr) で Stream を作ります。先頭 2 件を捨てる skip と、そこから 3 件だけ通す limit を、この順番でつないでください。最後に sum() で合計を取ります。自前の for で足し込むのは禁止です。
要素が 2 件しか無い配列を渡されたときは、捨てた時点で何も残らないので、合計は 0 になります。ここでも長さを調べる if は要りません。
要件
- ファイル先頭で
import java.util.stream.IntStream;を書くこと IntStream.of(arr)でint[]からIntStreamを作り、.skip(2).limit(3)の順で中間操作を呼ぶこと- 終端操作
.sum()を呼んで合計をintでreturnすること (自前のforループで合計しないこと)
入出力例
windowSum([10,20,30,40,50,60]) → 120
windowSum([1,2,3,4,5]) → 12
windowSum([1,2]) → 0
windowSum([1,2,3]) → 3
windowSum([5,10,15,20,25,30,35,40]) → 60