1

I'm testing the collect method for streams. In this code I'm trying to build a single string from a stream of string by using a StringBuilder in the first case and concatenation of String in the second case. I am not understanding why the second case produces an empty 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 Answer 1

5

Well, the reason it doesn't work is that String is immutable.

String::new is a Supplier<String> that returns an empty String.

And your accumulator and combiner have no way of mutating it, since String is immutable.

Your code has the same effect as:

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

The calls to concat produce new Strings, and don't affect the value of the result String.

Since String is immutable, you can use immutable reduction (i.e. use reduce instead of collect):

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

This will have the same result as:

String s = "";
for (String str : strs) {
    s = s.concat(str);
}
1
  • 1
    Ok, so the collect method produces a mutable reduction. Thank you, I thought that it behaved just like the reduce method.
    – Matteo
    Commented Apr 27, 2021 at 10:17

Not the answer you're looking for? Browse other questions tagged or ask your own question.