Java 8 - Lambda expressions (Introduction and purpose) with examples
Hi, I am Malathi Boggavarapu working at Volvo Group and i live in Gothenburg, Sweden. I have been working on Java since several years and had vast experience and knowledge across various technologies.
This post teach you about Java 8 - Lambda expressions using some practical examples
Introduction to Lambda expressions
To understand it easily, lets start with FileFilter example.
public interface Filefilter{
boolean accept(File file);
}
public class JavaFileFilter implements FileFilter{
boolean accept(File file){
return file.getName().endsWith(".java")
}
}
JavaFileFilter fileFilter = new JavaFileFilter();
File dir = new File("d:/tmp");
File[] files = dir.listFiles(fileFilter);
2)
FileFilter fileFilter = new FileFilter(){
boolean accept(File file){
file.getName().endsWith(".java");
}
};
File dir = new File("d:/tmp");
File[] files = dir.listFiles(fileFilter);
Purpose of Lambda expressions
It is an another way of writing instances of anonymous classes and to make instances of anonymous classes easier to write and read!Example 1:
FileFilter filter = (File file) -> file.getName().endsWith(".java");
If more than one arguments then,
FileFilter filter = (File file, boolean test) -> {
file.getName().endsWith(".java");
println("test variable is :: " +test);
}
Example 2:
Runnable runnable = new Runnable(){
public void run(){
for(int i = 0; i < 10; i++){
println("i : " +i);
}
}
}
Runnable runnableLambda = () -> {
for(int i = 0; i < 10; i++){
println("i : " +i);
}
};
Type of lambda expression?
Type is a functional interface - interface with only one abstract methodEx: public interface Runnable{
run();
};
interface comparator(){
int compareTo();
}
Methods from object class don't count. If we declare some method from Object class, we need to define some documentation for that abstract method in the functional interface.
Functional interface can be annotated with @FunctionalInterface and it is optional. .
The compiler will check whether interface is functional or not if we annotate it. If the interface is not a FunctionalInterface then it throws an exception and the code does not compile
Can i put lambda in variable?
Yes! Lambda expressions can be stored in a variable and pass them as arguments to methods and return them as return values.Is a lambda expression an object?
If we see above examples, we have anonymous class and lambda expression. Anonymous class is created using keyword new. When we create an object with new keyword, it allocates some memory to the object, initiate static variables and call a constructor and so on. There is lot of overhead work done by the JVM here but in case of lambda all this overhead work does not exists and provide better performance than anonymous classes.It is a complex question to answer. JVM does not create a new object with lambda expression and the answer is No but not a clear No. Because it is recorded as an object inside the JVM and it is actually a new kind of object defined in java 8. Lambda is an object without an identity.
Lambda expression should not be used as an object.
Method references
Method references are the other way of writing lambda expression that is strictly equivalent to the normal way as writing lambda expressions.
Examples1) This lambda expression:
Consumer<String> c = s-> System.out.println(s);
Can be written like this
Consumer<String> c = System::out.println;
2) This lambda expression
Comparator<Integer> c = (i1, i2) -> Integer.compare(i1, i2);
can be written like this
Comparator<Integer> c = Integer::compare;
Processing data objects using Lambda expressions and Stream API
Usually objects will be stored in Collection (List, Map, Set) most of the time. So we will see here how the objects are accessed using lambda expressions.List<Customer> list = new ArrayList<Customer>();
1) list.forEach(customer -> System.out.println(customer));
2) list.forEach(System.out::println(customer));
Performance is same for both the above ways. Only readability matters
forEach is a method in Iterable interface. Well..in java8 we can add method implementation inside the interface. It allows to change the old interfaces without breaking the existing implementations. If we see forEach method in Iterable interface, according to Java7 it should be implemented in all classes which implements Iterable. But that is not possible to do. Though it is possible for jdk developers to change all the implementation classes, it does not work with custom Iterable implementation classes that exists in applications.
And by the way static methods are also allowed in interfaces. Earlier only static final variables are only allowed but now static methods are allowed too.
public interface Iterable<E>{
default void forEach(Consumer<E> consumer){
for(E e : this){
consumer.accept(e);
}
}
}
New patterns
Predicate : Is the functional interface inside java.util.FunctionPredicate<String> p1 = < -> s.length() < 20;
Predicate<String> p2 = < -> s.length() > 10;
Predicate<String> p3 = p1.and(p2);
"and" is the default method inside the functional interface of Predicate.
Example
List<String> strings = Arrays.asList("one", "two", "Three");
List<String> result = new ArrayList<String>();
//Consumer<String> c1 = s -> System.out.println(s);
Consumer<String> c1 = System.out::println(c1); // Method reference
//Consumer<String> c2 = s -> result.add(s);
Consumer<String> c2 = result::add; // Method reference
strings.forEach(c1.andThen(c2));
Here addThen is the default implementation method of Consumer functional interface.
Thank you so much for this useful article about Java 8 Lambda Expression Tutorial .
ReplyDeleteThanks for your acknowledgement and Welcome to my blog.
DeleteExplanation super ��
ReplyDelete