Search code examples
javajava-streamcollect

Collect method for streams doesn't work as expected


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);

Solution

  • 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);
    }