Java 8ストリームskip()およびlimit()

1. 前書き

この短い記事では、https://www.baeldung.com/java-8-streams [Java Stream API]の_skip()_および_limit()_メソッドについて説明し、それらの類似点と相違点を強調します。
これらの2つの操作は、最初は非常に類似しているように見えますが、実際には非常に異なる動作をし、互換性はありません。 実際、これらは補完的なものであり、一緒に使用すると便利です。 それらについての詳細を学ぶために読んでください。

2. _skip()_メソッド

_skip(n)_メソッドは、ストリームの最初の_n_要素を破棄する*中間操作です*。 _n_パラメーターは負の値にできません。また、ストリームのサイズよりも大きい場合、_skip()_は空のストリームを返します。
例を見てみましょう。
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(i -> i % 2 == 0)
    .skip(2)
    .forEach(i -> System.out.print(i + " "));
このストリームでは、ストリームの偶数をピックアップしていますが、最初の2つはスキップします。 したがって、結果は次のとおりです。
6 8 10
このストリームが実行されると、_forEach_はアイテムの要求を開始します。 _skip()_に到達すると、この操作は最初の2つの項目を破棄する必要があることを認識しているため、結果のストリームにそれらを追加しません。 その後、残りのアイテムを含むストリームを作成して返します。
これを行うには、_skip()_操作で、各瞬間に表示される要素の状態を維持する必要があります。 このため、* _ skip()_はステートフル操作*であると言います。

3. _limit()_メソッド

_limit(n)_メソッドは、要求されたサイズ以下のストリームを返す別の*中間操作*です。 前と同様に、_n_パラメーターを負の値にすることはできません。
例で使用してみましょう。
Stream.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
    .filter(i -> i % 2 == 0)
    .limit(2)
    .forEach(i -> System.out.print(i + " "));
この場合、_int_のストリームから2つの偶数のみを取得しています。
2 4
_skip()_操作の場合と同様に、_limit()_は、ピックアップされるアイテムの状態を保持する必要があるため、ステートフル操作でもあります。
ただし、ストリーム全体を消費する_skip()_とは異なり、_limit()_はアイテムの最大数に達するとすぐに、それ以上アイテムを消費せず、結果のストリームを返します。 したがって、* _ limit()_は短絡操作*であると言います。
無限ストリームを使用する場合、_limit()_はストリームを有限に切り捨てるのに非常に役立ちます。
Stream.iterate(0, i -> i + 1)
    .filter(i -> i % 2 == 0)
    .limit(10)
    .forEach(System.out::println);
この例では、数値の無限ストリームを切り捨てて、偶数が10個だけのストリームにします。

*4. skip()_と_limit() *の組み合わせ

前に述べたように、_skip_と_limit_の操作は相補的であり、それらを組み合わせると、場合によっては非常に役立ちます。
前の例を修正して、10個のバッチで偶数を取得することを想像してみましょう。 同じストリームで_skip()_と_limit()_の両方を使用するだけで簡単に実行できます。
private static List<Integer> getEvenNumbers(int offset, int limit) {
    return Stream.iterate(0, i -> i + 1)
        .filter(i -> i % 2 == 0)
        .skip(offset)
        .limit(limit)
        .collect(Collectors.toList());
}
ご覧のとおり、このメソッドを使用すると、ストリームを簡単にページ分割できます。 これは非常に単純なページネーションですが、ストリームをスライスするときにこれがどれほど強力であるかを見ることができます。

5. 結論

この短い記事では、Java Stream APIの_skip()_メソッドと_limit()_メソッドの類似点と相違点を示しました。 また、これらのメソッドの使用方法を示すために、いくつかの簡単な例を実装しました。
いつものように、例の完全なソースコードが利用可能です。https://github.com/eugenp/tutorials/tree/master/core-java-modules/core-java-8-2 [GitHubで]