Метод сбора потоков работает не так, как ожидалось

#java #java-stream #collect

Вопрос:

Я тестирую collect метод на потоках. В этом коде я пытаюсь построить одну строку из потока строк, используя a StringBuilder в первом случае и объединение String во втором случае. Я не понимаю, почему во втором случае получается пустая строка.

     String[] strs = new String[] {"aaaaa", "bbbbbbb", "c", "dd"};
    
    
    StringBuilder sb = Arrays.stream(strs).collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
    
    System.out.println(sb);
    
    
    String s = Arrays.stream(strs).collect(String::new, String::concat, String::concat);
    
    System.out.println(s);
 

Ответ №1:

Ну, причина, по которой это не работает, в том, что String это непреложно.

String::new является a Supplier<String> , которое возвращает пустое String значение .

И ваш накопитель и объединитель не могут его изменить, поскольку String он неизменен.

Ваш код имеет тот же эффект, что и:

 String s = new String ();
for (String str : strs) {
    s.concat(str);
}
 

Вызовы для concat создания новых String s и не влияют на значение результата String .

Поскольку String является неизменяемым, вы можете использовать неизменяемое сокращение (т. Е. Использовать reduce вместо collect ):

 String s = Arrays.stream(strs).reduce("",String::concat);
 

Это приведет к тому же результату, что и:

 String s = "";
for (String str : strs) {
    s = s.concat(str);
}
 

Комментарии:

1. Хорошо, итак, метод сбора производит изменяемое сокращение. Спасибо, я думал, что он вел себя точно так же, как метод сокращения.