Рубрики
Без рубрики

Пропуск потока Java 8() против ограничения()

Изучите разницу между методами skip() и limit() в потоковом API Java 8.

Автор оригинала: Marcos Lopez Gonzalez.

1. введение

В этой короткой статье мы поговорим о методах skip() и limit() API Java Stream и выделим их сходства и различия.

Несмотря на то, что на первый взгляд эти две операции могут выглядеть довольно похожими, на самом деле они ведут себя совершенно по-разному и не являются взаимозаменяемыми. На самом деле они дополняют друг друга и могут быть удобны при совместном использовании. Продолжайте читать, чтобы узнать о них больше.

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 + " "));

В этом потоке мы собираем четные числа потока, но пропускаем первые два. Поэтому наш результат таков:

6 8 10

Когда этот поток выполняется, forEach начинает запрашивать элементы. Когда он попадает в skip() , эта операция знает, что первые два элемента должны быть отброшены, поэтому она не добавляет их в результирующий поток. После этого он создает и возвращает поток с оставшимися элементами.

Для этого операция 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 4

Как и в случае с операцией skip () , limit() также является операцией с сохранением состояния, поскольку она должна сохранять состояние собираемых элементов.

Но в отличие от skype() , который потребляет весь поток, как только limit() достигает максимального количества элементов, он не потребляет больше элементов и просто возвращает результирующий поток. Следовательно, мы говорим, что limit() является операцией короткого замыкания .

При работе с бесконечными потоками limit() может быть очень полезен для усечения потока в конечный:

Stream.iterate(0, i -> i + 1)
    .filter(i -> i % 2 == 0)
    .limit(10)
    .forEach(System.out::println);

В этом примере мы усекаем бесконечный поток чисел в поток, содержащий только десять четных чисел.

4. Комбинирование пропусков() и ограничений()

Как мы упоминали ранее, операции пропустить и ограничить дополняют друг друга, и если мы их объединим, они могут быть очень полезны в некоторых случаях.

Давайте представим, что мы хотим изменить наш предыдущий пример так, чтобы он получал четные числа партиями по десять. Мы можем сделать это просто, используя как skip () , так и limit() в одном потоке:

private static List 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. Заключение

В этой краткой статье мы показали сходства и различия методов skip() и limit() API потока Java. Мы также реализовали несколько простых примеров, чтобы показать, как мы можем использовать эти методы.

Как всегда, полный исходный код примеров доступен на GitHub .