2

I'm studying Stream APIs in Java 8 and I'm facing a problem. The problem is I'm trying to understand the differences between ()->new StringBuilder and StringBuilder::new in the following code:

Stream<String> stream = Stream.of(new String[]{"b", "a", "s", "i", "l",});
StringBuilder basil = stream.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append);
System.out.println("basil");

and

Stream<String> stream = Stream.of(new String[]{"b", "a", "s", "i", "l",});
    StringBuilder basil = stream.collect(()->new StringBuilder(), StringBuilder::append, StringBuilder::append);
    System.out.println("basil");

When should I use the first syntax, and when should I choose the second one?

And why the above code accept StringBuilder::append and doesn't accept StringBuilder::reverse

Basil Battikhi
  • 2,638
  • 1
  • 18
  • 34
  • They are functionally equivalent. The second is called a ['method reference'](https://docs.oracle.com/javase/tutorial/java/javaOO/methodreferences.html). – Michael Mar 20 '18 at 15:41
  • Both is equivalent. I would recommend using the method references if possible, since its more compact and in my opinion more readable. It's opinion based. – Zabuzard Mar 20 '18 at 15:42
  • 1
    @Zabuza It's not always more compact. A private static method is often more verbose when written as a method reference. – Michael Mar 20 '18 at 15:43
  • Yeah, go for whatever you find more readable and appropriate in a specific situation. – Zabuzard Mar 20 '18 at 15:43
  • it's mainly "the same" thing, if you *really* care, the method reference will create one less synthetic method – Eugene Mar 20 '18 at 19:32

1 Answers1

8

The lambda expression (()->new StringBuilder()) and the method reference (StringBuilder::new) you are asking about are equivalent. Use whichever looks more readable to you.

As for the second question:

Consider the signature of collect:

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

The second argument is a BiConsumer whose first parameter is the type of the output of the collect operation and whose second parameter is the type of the Stream element. In your case you need a BiConsumer<StringBuilder,String>. StringBuilder append(String str) matches this functional interface, since it has a StringBuilder input (the instance on which it is called) and a String input.

StringBuilder reverse() doesn't match this functional interface, since it only has a StringBuilder input and no String input.

Eran
  • 387,369
  • 54
  • 702
  • 768