Как метод lower () работает с параллельными потоками в Java 8? - PullRequest
1 голос
/ 07 мая 2019

Я пытаюсь понять, как метод reduce() работает точно с параллельными потоками, и я не понимаю, почему следующий код не возвращает конкатенацию этих строк.

Это код:

public class App {

    public static void main(String[] args) {
        String[] grades = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K"};

        StringBuilder concat = Arrays.stream(grades).parallel()
                .reduce(new StringBuilder(),
                        (sb, s) -> sb.append(s),
                        (sb1, sb2) -> sb1.append(sb2));

        System.out.println(concat);

    }
}

Код работает только с последовательными потоками, но с параллельными потоками не возвращает конкатенацию.Выходной каждый раз отличается.Может кто-нибудь объяснить мне, что там происходит?

1 Ответ

1 голос
/ 08 мая 2019

Проблема в том, что вы используете Stream::reduce для Изменяемое сокращение , для которого специально разработано Stream::collect. Может использоваться как для безопасного параллельного хранения. Читайте о различиях также в официальной документации Oracle Streams: Reduction . В отличие от метода lower, который всегда создает новое значение при обработке элемента, метод collect изменяет или изменяет существующее значение.

Обратите внимание на отличия обоих методов от их JavaDoc:

Поэтому я предлагаю вам сделать следующее:

StringBuilder concat = Arrays.stream(grades)
    .parallel()
    .collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
...