1. введение
Потоковый API был одной из ключевых функций, добавленных в Java 8.
Вкратце, API позволяет нам обрабатывать коллекции и другие последовательности элементов – удобно и более эффективно – предоставляя декларативный API.
2. Примитивные потоки
Потоки в основном работают с коллекциями объектов, а не с примитивными типами.
К счастью, чтобы обеспечить способ работы с тремя наиболее часто используемыми типами примитивов – int, long и double – стандартная библиотека включает в себя три специализированные реализации примитивов: IntStream , LongStream, и DoubleStream .
Примитивные потоки ограничены в основном из-за накладных расходов на бокс и потому, что создание специализированных потоков для других примитивов во многих случаях не так полезно.
3. Арифметические Операции
Давайте начнем с нескольких интересных методов для часто используемых арифметических операций, таких как min , max , sum и average:
int[] integers = new int[] {20, 98, 12, 7, 35}; int min = Arrays.stream(integers) .min() .getAsInt(); // returns 7
Давайте теперь пройдемся по приведенному выше фрагменту кода, чтобы понять, что происходит.
Мы создали наш IntStream с помощью java.util.Arrays.stream(int []) , а затем использовал метод main () , чтобы получить наименьшее целое число как java.util.OptionalInt и, наконец, вызвал getAsInt () , чтобы получить значение int .
Другим способом создания IntStream является использование IntStream.of(int…) . Метод max() вернет наибольшее целое число:
int max = IntStream.of(20, 98, 12, 7, 35) .max() .getAsInt(); // returns 98
Далее – чтобы получить сумму целых чисел, мы просто вызываем метод sum () , и нам не нужно использовать getAsInt () , так как он уже возвращает результат в виде значения int :
int sum = IntStream.of(20, 98, 12, 7, 35).sum(); // returns 172
Мы вызываем метод average () , чтобы получить среднее значение целочисленных значений, и, как мы видим, мы должны использовать getAsDouble () , поскольку он возвращает значение типа double .
double avg = IntStream.of(20, 98, 12, 7, 35) .average() .getAsDouble(); // returns 34.4
4. Диапазон
Мы также можем создать Instagram на основе диапазона:
int sum = IntStream.range(1, 10) .sum(); // returns 45 int sum = IntStream.rangeClosed(1, 10) .sum(); // returns 55
Как показано в приведенном выше фрагменте кода, существует два способа создания диапазона целочисленных значений range() и range Closed() .
Разница в том, что конец range() является исключительным, в то время как он включен в range Closed() .
Методы диапазона доступны только для Instream и Long Stream .
Мы можем использовать диапазон как причудливую форму цикла для каждого:
IntStream.rangeClosed(1, 5) .forEach(System.out::println);
Что хорошо в использовании их в качестве замены для каждого цикла, так это то, что мы также можем воспользоваться преимуществами параллельного выполнения:
IntStream.rangeClosed(1, 5) .parallel() .forEach(System.out::println);
Как бы ни были полезны эти причудливые циклы, все же лучше использовать традиционные циклы for вместо функциональных для простых итераций из-за простоты, удобочитаемости и производительности в некоторых случаях.
5. Бокс и распаковка
Бывают моменты, когда нам нужно преобразовать примитивные значения в их эквиваленты оболочки.
В этих случаях мы можем использовать метод boxed() :
ListevenInts = IntStream.rangeClosed(1, 10) .filter(i -> i % 2 == 0) .boxed() .collect(Collectors.toList());
Мы также можем преобразовать поток класса-оболочки в примитивную полосу:
// returns 78 int sum = Arrays.asList(33,45) .stream() .mapToInt(i -> i) .sum();
Мы всегда можем использовать методы mapToXxx и flatMapToXxx для создания примитивных потоков.
6. Заключение
Потоки Java – это очень мощное дополнение к языку. Мы едва поцарапали поверхность примитивных потоков здесь, но, как вы уже можете использовать их, чтобы быть продуктивными.
И, как всегда, примеры кода можно найти на GitHub .