Page 1 of 1
About Question enthuware.ocpjp.v8.2.1801 :
Posted: Mon Jul 18, 2016 4:13 pm
by lexer24
Hi,
Could you please explain me why
java.util.Stream method
void forEach(Consumer<? super T> action) is aplicable for
public StringBuilder append(String str) method of
StringBuilder class? So this becomes legal:
messages.stream().forEach(s->s.append("helloworld"));
As for me,
append method returns reference to StringBuilder but
forEach expects
Comsumer which means
void return type.
If we dig deeper then we will come to the following legal code:
Code: Select all
...
Consumer<StringBuilder> cm = s -> s.append("helloworld");
Function<StringBuilder, StringBuilder> r3 = s -> s.append("helloworld");
...
How does Java manage this?
Best regards,
Aleksei
Re: About Question enthuware.ocpjp.v8.2.1801 :
Posted: Mon Jul 18, 2016 10:07 pm
by admin
Returns type of append has no relation to the type that forEach expects. Think of it these three steps -
1. The Java compiler creates a dummy inner class of the type that is expected by forEach (i.e. Consumer, in this case).
2. It adds a method to this dummy class. This method implements the abstract method of the Consumer interface.
3. It adds the code that you write in your lambda expression into the method that it created in step 2.
So forEach(s->s.append("asdf")), gets converted into:
Code: Select all
forEach( new Consumer(){
public void accept(StringBuilder s){
s.append("asdf");
}
}
You have asked a very basic question about lamdas. You should have learnt this for OCAJP 8 itself. So I will suggest you to read this topic from a good book or follow Java Tutorial on lambdas. You can also read this short article to begin with:
http://enthuware.com/index.php/home/115
HTH,
Paul.
Re: About Question enthuware.ocpjp.v8.2.1801 :
Posted: Tue Jul 19, 2016 5:15 am
by lexer24
Hi,
Thank you for the answer.
Don't get me wrong I know how lambdas work.
As for me, in my example there is an ambiguous situation, because lambda:
could be treated either as such
or
Code: Select all
s -> {return s.append("helloworld");}
And that was the question, how does Java know which one to choose while applying the lambda?
Will try also to find this information in documentation. Thank you again.
Best regards,
Aleksei
Re: About Question enthuware.ocpjp.v8.2.1801 :
Posted: Tue Jul 19, 2016 5:39 am
by admin
Compiler makes this decision based on the funtional interface applicable in the given situation. Here, the interface is Consumer, whose functional method doesnt return anything.
Re: About Question enthuware.ocpjp.v8.2.1801 :
Posted: Wed Oct 23, 2019 3:17 pm
by dongyingname
Code: Select all
List<StringBuilder> messages = Arrays.asList(new StringBuilder(), new StringBuilder());
messages.stream().forEach(s->s.append("helloworld"));
messages.forEach(s->{
s.insert(5,","); System.out.println(s);
});
.stream() makes a copy of underlying List, which is messages. Why could the .forEach() eventually affect the original messages?
Could you please also provide simple examples where pipeline doesn't affect the original List?
Re: About Question enthuware.ocpjp.v8.2.1801 :
Posted: Wed Oct 23, 2019 9:02 pm
by admin
1. Where did you read that .stream() makes a copy of underlying List??
2. Assuming for a second that even if it made copy of the list (it does not), the objects in the list are the same that you get the in the stream. So, the call to s.append will modify the same object.
3. If you don't want to affect elements of the original list, you need to make a deep copy first. See this:
https://stackoverflow.com/questions/478 ... ect=1&lq=1