java8 + internal working of for each loop - java

I am new to java8. I was trying to understand working of foreach loop in Streams.
My code is as follows:-
Stream<String> s = someist.stream();
Consumer<String> consumer = (String s1)->System.out.println(s1);
s.forEach(consumer);
Question is how does foreach loop know to call consumer.accept(T t) when i am just passing the reference of Consumer and not calling consumer.accept(T t) inside it. Although, when we provide some lambda expression for a functional interface we need to call its abstract method, we are just not calling it here.
So how does foreach loop comes to know what should it do with the consumer reference provided as a parameter?

The concrete implemention of forEach will call accept, for example:
public class MyStream implements Stream<String> {
#Override
public void forEach(Consumer<? super String> action) {
while (hasNext()) {
action.accept(next());
}
}
...
}

As the java doc states:
void forEach​(Consumer<? super T> action)
Performs an action for each
element of this stream.
i.e the behavioural parameter passed to the forEach method will be called internally for each element of the source.

This is how Functional Interface works. They have only one abstract method. There might be optional default methods. The behaviour of the abstract method is passed in form of lambda expression (passing behaviour as if data). This behaviour is, in turn, the method body for the abstract method of the Functional Interface. The default methods are called using their names.
So when you pass a Functional Interface as a method parameter to another method, in this case, Consumer<T> to the forEach() method of java.util.stream.Stream interface, its abstract method accept(T t) is called for each item of the stream.
Put it this way, logically, there's only one method to be invoked if only the Functional Interface is passed as a parameter.

Related

Can you explain why the first unwrapped method reference does not compile?

In this example, passing a method reference to Stream.of does not work but once it's wrapped it works. I can't quite get my head around why this is. Isn't the method reference equivalent to the functional interface?
public class A {
String a() {
return "";
}
void b() {
Stream.of(this::a); // won't compile
Stream.of(wrap(this::a)); // will compile
}
static <T> Supplier<T> wrap(Supplier<T> f) {
return f;
}
}
Stream.of has the following signature:
public static<T> Stream<T> of(T t)
The following example will compile because you explicitly providing a type information for T.
Stream<Supplier<String>> a = Stream.of(this::a);
The first example Stream.of(this::a); equivalent to:
Object a = this::a;
where Object is not a functional interface and will not compile.
Providing with a functional interface this example compiles:
Runnable a = this::a;
Stream.of(a);
In the second example, wrap provides a functional interface Supplier
Stream.of(T) expects an Object and you pass to it a method reference in the first statement. But an Object parameter is not a functional interface, so it cannot accept a method reference or a lambda that is not specifically typed.
With lambda, it would produce also an error : Stream.of(()->this.a()).
A simpler example could be Stream.of(()-> "foo") that will just not compile.
But if you type the method reference or the lambda it works :
Stream.of((Supplier<String>) this::a)
or
Stream.of((Supplier<String>) () -> this.a())
In the working statement you pass to Stream.of(T) a parameter that is a Supplier<String>. That refers to a functional interface but that is typed as in the previous working examples, so it is valid as parameter that expects an Object.
this::a is contextless and could mean different things. You need to provide some context to help the compiler to figure out what you actually meant by this::a.
Stream.<Supplier<String>>of(this::a);
Though, that Stream<Supplier<String>> doesn't seem to be what you wanted. If you need a Stream<String>, use Stream.generate: no extra type information needed since the method takes a Supplier<T> (no ambiguity here).
Stream.generate(this::a);
On a side note, both statements expect you to save their results into variables. Defining variables of the right type often facilitates resolving such issues.
Stream<Supplier<String>> s1 = Stream.of(this::a);
Stream<String> s2 = Stream.generate(this::a);
All credit to #J-Alex and #Holger for their precious comments.

Is it possible to use method reference with static method of interface?

This is my first code:
public class MethodReference {
public static void main (String []args) {
Stream<String> s = Stream.of("brown bear", "grizzly");
s.sorted(Comparator.reverseOrder()).forEach(System.out::print);
//...
}
}
Result: grizzlybrown bear
This is my second code:
public class MethodReference {
public static void main (String []args) {
Stream<String> s = Stream.of("brown bear", "grizzly");
s.sorted(Comparator::reverseOrder()).forEach(System.out::print);
//...
}
}
Result: compiler error
My questions:
Why is there a compiler error in the second code?
Can't I use the method reference for static method of functional interface?
I know I can't use method reference with default method of functional interface.
I know I can use method reference with a class in 5 cases:
Class
Class::staticMethod
Class::instanceMethod
instance::instanceMethod
Class::new
Functional Interface
Interface::abstractMethod
Thanks a lot!
Comparator.reverseOrder() is an expression which resolves to the Comparator type, because that's what it returns.
Comparator::reverseOrder is an expression which resolves to a method which takes no arguments and returns a Comparator e.g. a Supplier<Comparator<String>>, though it could be any matching functional interface.
In the second instance you are trying to pass a method (which provides a Comparator) as an argument. The method doesn't want that - it just wants the Comparator itself.
You could think of it like this (just pseudo-code to demonstrate the point):
s.sorted(new Comparator())
vs
s.sorted(new Supplier(new Comparator()))
To answer your second question as to whether it's ever possible to use a method reference for a static method of an interface - yes, absolutely!
If we declare the following method:
<T> void giveMeAComparatorSupplier(Supplier<Comparator<T>> supplier) { }
then we can definitely call it with a method reference
giveMeAComparatorSupplier(Comparator::reverseOrder);
(And FYI your method reference syntax is wrong - it never uses ())
Two things are wrong with your second code. First, method references do not use parentheses or arguments at all. You would need to supply only the method that would be called later; you are not calling the method at that point.
Second, the sorted method takes a Comparator, not a functional interface that would supply a Comparator. The method needs a Comparator already created and ready to go, not a functional interface that will supply a Comparator when needed.
It has nothing to do with the fact that Comparator is an interface; one can generally create a method reference to a static interface method. It has everything to do with the fact that sorted needs an actual Comparator instance and not an instance of a functional interface, which is when you could supply a method reference.
So even if you take off the parentheses, it still won't compile. Only your first code, which directly passes a Comparator, will compile and work as expected.

Does lambda expression automatically create new object for its entry parameters?

I am new to functional programming, so far i have understood how to use it, anonymous function etc.
I saw many examples of code where the object needed as parameter in my lambda expression actually doesn't exist in that moment (it isn't instantiated).
For example, is this:
myClass.myMethod(c -> {my overridden code});
the same as this
myClass.myMethod(new String() -> {my overridden code});
considering that c is not declared in my code and myMethod correctly implements a functional interface which abstract method requires a String?
EDIT:
I got some problems with this question:
JavaFX ComboBox Image
With this part of code:
comboBox.setCellFactory(c -> new StatusListCell());
I can't figure out where c is taken from, it's not declared at all, that's why i was wondering if lambda expressions could create new objects automatically.
c is actually only a placeholder, like a parameter in a method would be (which does not differ from the functioning of the lambda here).
myClass.myMethod(c -> {my overridden code});
is the equivalent of the following
myClass.myMethod(new Consumer<String>(){
#Override
public void accept(String c) {
{my overridden code}
}
}
So the answer to your question is : No. The lambda represents a method, a function but is not an executable piece by itself, it has to be invoked with outside parameters.

How does forEach() method works in Java 8

I am writing a snippet:
List<Integer> list=Arrays.toList(2,4,6,8);
list.forEach(i -> System.out.println(i));
Please explain me the flow of method call in the above snippet. How the forEach() method is passing the parameters to the accept() method? Does the forEach() method calls the accept method each time?
Please correct me if I am wrong.
i-> System.out.println(i)
returns an object of Consumer interface. forEach() calls the accept() method of that object with i as the parameter.
Because Consumer is a functional interface, your lambda function can implicitly satisfy it. So when you do
list.forEach(i -> System.out.println(i));
what you're doing conceptually (more below) is
list.forEach(new Consumer<String>() {
#Override
public void accept(String i) {
System.out.println(i);
}
});
The instance is then passed into forEach, which calls its accept method for each entry in the list.
From a comment you made on the question:
I am confused which method is invoked first. Is it the "forEach()" or the "accept ()" because both of them are working togather!
The order of things is:
An instance of the anonymous class is created (in effect, via the invokedynamic operation)
forEach is called, passing in that reference
forEach's code calls accept repeatedly, each time passing one of the list items into it (which it receives as i)
Note I said conceptually. An anonymous class isn't really created by the compiler; instead, a new bytecode operation called invokedynamic is used to create the consumer instance.

What does "call" mean in this java code

I have a working understanding of Java. I understand reserved words. I also understand the basics of anonymous classes. I am reading this Spark example and see a "call" statement. What is the meaning of call and #Override? I see that call is not a reserved word -- but I also don't see it in the Spark docs or in the import statement. Could someone break down what is happening in this code? I get that it passes an anonymous class as a parameter (right?) -- and then that abstract class has an anonymous method called "call" (right?). But what is getting overwritten? Why the #Override? What does call refer to?
JavaPairRDD<String, Integer> ones = words.mapToPair(new PairFunction<String, String, Integer>() {
#Override
public Tuple2<String, Integer> call(String s) {
return new Tuple2<String, Integer>(s, 1);
}
});
PairFunction is an interface that has a single method named call. What's happening here is that an implementation of this interface is being created and passed as a parameter to words.mapToPair.
It might be a bit simpler to understand if you see an equivalent (but more verbose) way to do the same thing:
class PairFunctionImpl implements PairFunction<String, String, Integer> {
#Override
public Tuple2<String, Integer> call(String s) {
return new Tuple2<String, Integer>(s, 1);
}
}
JavaPairRDD<String, Integer> ones = words.mapToPair(new PairFunctionImpl());
The code you've shown is functionally identical to this, except implementing the interface, creating an instance, and passing this instance as a parameter to words.mapToPair is done in a single step via an anonymous class.
The #Override annotation tells the compiler to check that the call method signature matches the definition in the PairFunction interface, which has the following benefits:
Provides a safeguard against typos
Enhances code readability by making it clearer which methods in a class are defined in an implemented interface or extended class
In this particular case, you don't get much benefit from #Override because you would get a compile-time error even without it (use of #Override is always optional), but personally I always use it.
What you see in this snippet is the instantiation of an anonymous class that implements spark.api.java.function.PairFunction. call is a method in that interface that should be implemented, and #Override signifies that this method is defined in the interface (as opposed to just adding another method to the one you're implementing).
Note: that same syntax holds for extending an abstract class, although this is not the case here.
You have a few questions
"I get that it passes an anonymous class as a parameter (right?)" Not quite, an anonymous class is not being passed, what is passed is an instance of the anonymous class defined above which implements the PairFunction interface. You later refer to this object as an abstract class, it is not abstract either. You can't construct (call new on) an abstract class. The class you just instantiated is concrete and not abstract. Just anonymous.
The meaning of call: This is the name of a method which any class implementing the PairFunction interface has to implement. What it actually does is a Spark question, but I gather from the java docs that it triggers the pairing function.
Meaning of #Override: This is an annotation which is used to indicate that the method you are now defining overrides the implementation in a parent class. In this case you aren't actually overriding any existing implementation as only an interface exists but that's the convention. The annotation has no impact on the run-time execution. I'll refer you to this question for more details on when to use it.

Categories

Resources