Поток.метод peek () в Java 8 против Java 9


Я нахожусь в процессе обучения с помощью Java 8 лямбда-выражений и хотел бы спросить о следующем фрагменте кода Java, относящемся к peek метод в интерфейсе функции, с которым я столкнулся.

при выполнении программы на IDE, он не дает никакого результата. Я ожидал, что это даст 2, 4, 6.

import java.util.Arrays;
import java.util.List;

public class Test_Q3 {

    public Test_Q3() {
    }

    public static void main(String[] args) {
        List<Integer> values = Arrays.asList(1, 2, 3);
        values.stream()
              .map(n -> n * 2)
              .peek(System.out::print)
              .count();
    }
}
2 58

2 ответа:

Я предполагаю, что вы используете это под Java 9? Вы не изменяете SIZED свойства потока, поэтому нет необходимости выполнять либо map или peek на всех.

другими словами, все, что вас волнует count как конечный результат, но в то же время вы не изменяете начальный размер List на любой способом (через или distinct) это оптимизация, выполненная в потоках.

кстати, даже если вы добавляете манекен фильтр это покажет, что вы ожидаете:

values.stream ()
      .map(n -> n*2)
      .peek(System.out::print)
      .filter(x -> true)
      .count();

вот некоторые соответствующие цитаты из Javadoc из поток интерфейс:

реализация потока допускает значительную широту в оптимизации вычисления результата. Например, реализация потока свободна от операций elide (или целых этапов) из конвейера потока-и, следовательно, вызов elide поведенческих параметров-если он может доказать, что это не повлияет на результат вычисления. Это означает, что побочные эффекты поведенческих параметров не всегда могут быть выполнены и не следует полагаться, если не указано иное (например, терминальные операции forEach и forEachOrdered). (Конкретный пример такой оптимизации см. В примечании API, описанном в операции count (). Дополнительные сведения см. В разделе побочные эффекты документации по пакету stream.)

и более конкретно из Javadoc из count () метод:

API Примечание:

реализация может не выполнять конвейер потока (либо последовательно, либо параллельно), если она способна вычислять количество непосредственно из источника потока. В таких случаях никакие исходные элементы не будут пройдены и никакие промежуточные операции не будут оцениваться. Поведенческие параметры с побочными эффектами, которые сильно обескуражены за исключением безвредных случаев как отладка, может быть затронута. Например, рассмотрим следующий поток:

List<String> l = Arrays.asList("A", "B", "C", "D");
long count = l.stream().peek(System.out::println).count();

количество элементов, охватываемых источником потока, списком, известно, и промежуточная операция, peek, не вводит и не удаляет элементы из потока (как это может быть в случае операций flatMap или filter). Таким образом, счетчик-это размер списка, и нет необходимости выполнять конвейер и, как побочный эффект, распечатывать элементы списка.

эти цитаты только появляются на Javadoc Java 9, так что это должна быть новая оптимизация.