Java 8 Потоки промежуточных операций производят новые потоки? - PullRequest
4 голосов
/ 14 марта 2020

Когда я вызываю промежуточные операции над потоками, создают ли они новый поток для каждой промежуточной операции?

List<Integer> list = List.of(1,2,3,4,5);

list.stream().filter(i -> i > 4).map(o -> o*2).collect(Collectors.toList());

Сколько потоков было создано? 1 или 3?

Ответы [ 3 ]

4 голосов
/ 14 марта 2020

По сути, одна из концепций функционального программирования - pure functions, которая определяет c и не имеет побочного эффекта, который называется immutability. Все промежуточные операции в API Stream являются неизменяемыми и возвращают новый поток.

Как указано в документе Oracle, все промежуточные операции, такие как filter, map и et c возвращает новый поток. Например, документ метода map выглядит следующим образом:

Stream<R> map(Function<? super T,? extends R> mapper)

Возвращает поток, состоящий из результатов применения данной функции к элементам этого потока. Это промежуточная операция.

Параметры типа: R - тип элемента нового потока Параметры:

mapper - не мешающая функция без сохранения состояния, применяемая к каждому элементу

Возвращает: новый поток

Для получения дополнительной информации вы можете взглянуть на реализацию Stream в Java (например, метод map, который возвращает новый StatelessOp)

public final <R> Stream<R> map(Function<? super P_OUT, ? extends R> mapper) {
    Objects.requireNonNull(mapper);
    return new StatelessOp<P_OUT, R>(this, StreamShape.REFERENCE,
                                 StreamOpFlag.NOT_SORTED | StreamOpFlag.NOT_DISTINCT) {
        @Override
        Sink<P_OUT> opWrapSink(int flags, Sink<R> sink) {
            return new Sink.ChainedReference<P_OUT, R>(sink) {
                @Override
                public void accept(P_OUT u) {
                    downstream.accept(mapper.apply(u));
                }
            };
        }
    };
}
3 голосов
/ 14 марта 2020

Одним словом - да. Каждый вызов такого метода создает еще один Stream объект. Вы могли бы увидеть это, если бы вы разорвали цепочку и присвоили эти промежуточные операции переменным, как вы go long:

Stream<Integer> s1 = list.stream();
System.out.println(System.identityHashCode(s1));
Stream<Integer> s2 = s1.filter(i -> i > 2);
System.out.println(System.identityHashCode(s2));
Stream<Integer> s3 = s2.map(o -> o*2);
System.out.println(System.identityHashCode(s3));
List<Integer> result = s3.collect(Collectors.toList());
System.out.println(result);

Пример вывода:

1163157884 1747585824 1149319664 [6, 8, 10]

2 голосов
/ 14 марта 2020

Да, вызов фильтра и сопоставления создает новый StatelessOp , который является новым ReferencePipeline , который реализует интерфейс Stream . Вы создаете 3 новых объекта StatelessOp.

...