What is the equivalent lambda expression for System.out::println
The method reference System.out::println
will evaluate System.out
first, then create the equivalent of a lambda expression which captures the evaluated value. Usually, you would useo -> System.out.println(o)
to achieve the same as the method reference, but this lambda expression will evaluate System.out
each time the method will be called.
So an exact equivalent would be:
PrintStream p = Objects.requireNonNull(System.out);
numbers.forEach(o -> p.println(o));
which will make a difference if someone invokes System.setOut(…);
in-between.
Calling System.out.println() through a lambda expression
Your current attempt doesn't work because you're trying to declare a variable of type void
- the equivalent would fail in C# too. You need to declare a variable of a suitable functional interface, just like you use a delegate type in C#.
You can do it with a lambda expression, but it would be cleaner (IMO) to use a method reference:
import java.util.function.Consumer;
public class Test {
public static void main(String[] args) {
Consumer<Object> c1 = x -> System.out.println(x);
Consumer<Object> c2 = System.out::println;
c1.accept("Print via lambda");
c2.accept("Print via method reference");
}
}
Here the Consumer<T>
interface is broadly equivalent to the Action<T>
delegate in .NET.
Similarly you can use a method group conversion in C# rather than a lambda expression:
public static Action<object> WL = Console.WriteLine;
What is the use of System.out::println in Java 8
It's called a "method reference" and it's a syntactic sugar for expressions like this:
numbers.forEach(x -> System.out.println(x));
Here, you don't actually need the name x
in order to invoke println
for each of the elements. That's where the method reference is helpful - the ::
operator denotes you will be invoking the println
method with a parameter, which name you don't specify explicitly:
numbers.forEach(System.out::println);
Equivalent lambda expression, to get a property of every object in a list
Assuming that your name attribute is a String
, keep going with your Stream
pipeline. Collect the names using the built-in Collector
that joins the values with a separator in between each element: Collectors.joining
:
Returns a
Collector
that concatenates the input elements, separated by the specified delimiter, in encounter order.
You can remove the unnecessary Arrays.asList
, which is incorrect anyway; it takes an array, not a stream or a string, as an argument.
System.out.println(
dataSet.getAttributeList().stream()
.map(p -> p.getName())
.collect(Collectors.joining(" "))
);
You may also choose to use a method reference instead of a lambda expression:
.map(Attribute::getName)
is the type of System.out.println functional interface?
This part of code:
Consumer<Integer> consumer=System.out::println;
is equal to this lambda expression:
Consumer<Integer> consumer=i->System.out.println(i);
and above code block could be written in this way as an anonymous inner class using Consumer interface:
Consumer<Integer> consumer=new Consumer<Integer>(){
public void accept(Integer i){
System.out.println(i);
}
}
So "System.out.println" itself it is not a functional interface, but when you use :: you implicitly implement the Consumer interface.
Why my java lambda expression cannot work while its imperative style works properly?
As explained in What is the equivalent lambda expression for System.out::println, the method reference System.out::println
is not identical to the lambda expression x -> System.out.println(x)
.
The method reference captures the current value of System.out
, to invoke println
on it each time the function is invoked, rather than evaluating System.out
again each time as the lambda expression’s body does.
As also said, this rarely makes a difference, but here, it does. When you try to serialize the function, it will try to serialize all captured values, including the PrintStream
instance read from System.out
during the instantiation. The PrintStream
is not serializable and it would be quite challenging to implement a serializable PrintStream
fulfilling the expectations.
But it’s important to keep in mind that when you serialize the lambda expression x -> System.out.println(x)
or an equivalent class object and deserialize it in a different environment, the System.out
it will read there will evaluate to a different PrintStream
than in your original environment. This doesn’t matter when the distributed computing framework takes care to pipe everything printed to the standard output back to the originator.
But it’s important to keep in mind that static
fields which are not part of the serialized data may have different contents in different environments in general.
Related Topics
Processbuilder: Forwarding Stdout and Stderr of Started Processes Without Blocking the Main Thread
What's the Difference Between Primitive and Reference Types
How to Convert a String with Unicode Encoding to a String of Letters
How to Get the SQL of a Preparedstatement
How to Parse Date String to Date
Selenium Webdriver How to Resolve Stale Element Reference Exception
Why Does the Jtable Header Not Appear in the Image
Eventlistenerlist Firing Order
Javafx: Location Is Not Set Error
What's the Difference Between Map() and Flatmap() Methods in Java 8
Eclipse/Java Code Completion Not Working
How to Preserve Insertion Order in Hashmap
What Is Lazy Loading in Hibernate
Odd Behavior When Java Converts Int to Byte
How to Do the Equivalent of Pass by Reference for Primitives in Java
Why We Use If, Else If Instead of Multiple If Block If the Body Is a Return Statement