С помощью Stream API можно выражать сложные запросы обработки данных. Распространенные потоковые операции перечислены в табл. 5.1.
• С помощью методов filter, distinct, takeWhile (Java 9), dropWhile (Java 9), skip и limit можно фильтровать потоки данных и получать их срезы.
• Методы takeWhile, dropWhile работают эффективнее, чем filter, в случае отсортированного источника данных.
• С помощью методов map и flatMap можно извлекать элементы потоков данных и преобразовывать их.
• Используя методы findFirst и findAny, можно находить элементы потока данных. С помощью методов allMatch, noneMatch и anyMatch можно сопоставлять элементы потока с заданным предикатом.
• Эти методы реализуют сокращенную схему вычислений: вычисление прекращается сразу по обнаружении искомого; обрабатывать весь поток данных не требуется.
• С помощью метода reduce можно последовательно группировать все элементы потока для получения единого результата, например для вычисления суммы или максимума значений элементов потока данных.
• Часть операций, например filter и map, не сохраняют состояние. А некоторые, например reduce, для вычисления значения сохраняют состояние. Отдельные операции, такие как sorted и distinct, также сохраняют состояние, поскольку им необходимо буферизовать все элементы потока, чтобы вернуть новый поток. Подобные операции называются операциями с сохранением состояния.
• Существует три специализированные версии потоков для простых типов данных: интерфейсы IntStream, DoubleStream и LongStream. Их операции также специализированы соответствующим образом.
• Потоки данных можно создавать на основе не только коллекций, но и значений, массивов, файлов и с помощью конкретных методов, например iterate и generate.
• У бесконечного потока данных — бесконечное количество элементов (например, все возможные строки). Это возможно благодаря тому, что элементы в подобных потоках генерируются по требованию. С помощью таких методов, как limit, можно получить из бесконечного потока данных конечный.