Поток.метод 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 ответов


Я предполагаю, что вы используете это под 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, поэтому это должна быть новая оптимизация.