Что произойдет в терминальной операции collect () Stream, если поставщик является неизменным объектом, например String? - PullRequest
0 голосов
/ 12 сентября 2018

collect() метод Stream является изменяемым сокращением.Основано на документации Java:

Операция с изменяемым сокращением накапливает входные элементы в изменяемый контейнер результатов, такой как Collection или StringBuilder, так как обрабатывает элементы в потоке.

Я попробовал следующее, и он без проблем компилируется.

Stream<String> stream1 = Stream.of("w", "o", "l", "f");
String word = stream1.collect(String::new, String::concat, String::concat);
System.out.println(word);

Если поставщик является StringBuffer, я рассматриваю операцию сбора, так как элементы будут добавлены к прилагаемому StringBuffer.

Какработает ли изменяемое сокращение, поскольку String является неизменным объектом?Будет ли это так же, как операция при уменьшении, когда новый объект создается каждый раз при внедрении аккумулятора?

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

Как здесь работает изменяемое сокращение, поскольку String является неизменным объектом?

Это не так. При запуске вы получите пустую строку (результат Supplier only). Компилятор не может принудительно проверить, возвращает ли Поставщик неизменный объект, это абсолютно то, что он не может сделать. А поскольку ваш контейнер неизменен, обновления к нему просто игнорируются. Это как делать:

String s = "abc";
s.concat("def"); // the result is ignored here

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

Stream<String> stream1 = Stream.of("w", "o", "l", "f");
    String word = stream1.collect(
            String::new,
            (left, right) -> {
                left.concat(right); // result is ignored
            },
            String::concat);

С другой стороны, когда вы используете Reduce, вы вынуждены вернуть что-то:

String word = stream1.reduce(
            "",
            (x, y) -> {
                return x.concat(y);
            },
            (x, y) -> {
                return x.concat(y);
            });

Конечно, вы все равно можете сделать:

String word = stream1.reduce(
            "",
            (x, y) -> {
                x.concat(y);
                return x; // kind of stupid, but you could
            },
            (x, y) -> {
                return x.concat(y);
            });

Если вы хотели сломать это; но это не главное.

0 голосов
/ 12 сентября 2018

Согласно документации Oracle / Java:

собирать

<R> R collect(Supplier<R> supplier, <R,? super T> accumulator, <R,R> combiner)

Выполняет изменяемую операцию сокращения для элементов этого потока.Изменяемое сокращение - это такое, в котором уменьшенное значение представляет собой изменяемый контейнер результатов, такой как ArrayList, и элементы включаются путем обновления состояния результата, а не путем замены результата.

https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util.function.BiConsumer-java.util.function.BiConsumer-

Изменяемое сокращение

Операция изменяемого сокращения собирает входные элементы в изменяемый контейнер результатов, такой как Collection или StringBuilder, так как обрабатывает элементы впоток.Если бы мы хотели взять поток строк и объединить их в одну длинную строку, мы могли бы добиться этого с помощью обычного сокращения:

String concatenated = strings.reduce ("", String :: concat)

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html#MutableReduction

Итак, в двух словах, это работает, потому что за кулисами Java использует stringbuilder

...