Provide Best Programming Tutorials

Java 8 Lambda expressions

A very new and exciting feature, Java 8 ship with it, is java lambda expressions. They are not unknown to many of us who have worked on advanced languages like scala.

In fact, if you look at history and try to find out any language improvement in Java in last 2 decades, you will not be able to recall many exciting things. Only few concurrent classes, generics and if you agree then annotations as well, are remarkable additions in java in last decade. Lambda expressions break this drought and feels like a pleasant gift.

In this post, I will cover lambda expression and concepts around it in three parts. Below is out plan to go ahead.

1. What is a lambda expression in Java?

In programming, a Lambda expression (or function) is just an anonymous function, i.e., a function with no name and without being bounded to an identifier.In other words, lambda expressions are nameless functions given as constant values, and written exactly in the place where it’s needed, typically as a parameter to some other function.

The most important features of Lambda Expressions is that they execute in the context of their appearance. So, a similar lambda expression can be executed differently in some other context (i.e. logic will be same but results will be different based on different parameters passed to function).

Above definition is full of keywords and can be understood only when you already know in deep that what is lambda expression. So, once you got better understanding on lambda expressions in next sections, I advise you to re-read above paragraph.

So, it is clear that lambda is some kind of function without name and identifiers. Well, what’s big deal? Why everyone is so excited?

The answer lies in the benefits involved in functional programming over object oriented programming (OOP). Most OOP languages evolve around objects and instances and treat only them their first class citizens. Another important entity i.e. functions take back seat. This is specially true in java, where functions can’t exist outside an object. A function itself does not mean anything in java, until it is related to some object or instance.

But in functional programming, you can define functions, give them reference variables and pass them as method arguments and much more. JavaScript is a good example of this where you can pass callback methods e.g. to Ajax calls. It’s very useful feature and has been lacking in java from beginning. Now with java 8, we can also use these lambda expressions.

1.1. Lambda Syntax

A typical lambda expression syntax will be like this:

(x, y) -> x + y  //This function takes two parameters 
                    //and return their sum.

Now based on type of x and y, method may be used in multiple places. Parameters can match to int, or Integer or simply String also. Based on context, it will either add two integers or concat two strings.

Syntax:

The other possible syntaxes of a lambda expression are:

either
 
(parameters) -> expression           //1
 
or
 
(parameters) -> { statements; }  //2
 
or 
 
() -> expression                     //3

1.2. Lambda examples

Let’s see some examples of lambda expressions as well:

(int a, int b) ->    a * b               // takes two integers and returns their multiplication
 
(a, b)          ->   a - b               // takes two numbers and returns their difference
 
() -> 99                                // takes no values and returns 99
 
(String a) -> System.out.println(a)     // takes a string, prints its value to the console, and returns nothing 
 
a -> 2 * a                               // takes a number and returns the result of doubling it
 
c -> { //some complex statements }   // takes a collection and do some procesing

1.3. Features of Lambda Expressions

Let’s identify some features of lambda expression:

  1. A lambda expression can have zero, one or more parameters.
  2. The type of the parameters can be explicitly declared or it can be inferred from the context.
  3. Multiple parameters are enclosed in mandatory parentheses and separated by commas. Empty parentheses are used to represent an empty set of parameters.
  4. When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a.
  5. The body of the lambda expressions can contain zero, one or more statements.
  6. If body of lambda expression has single statement curly brackets are not mandatory and the return type of the anonymous function is the same as that of the body expression. When there is more than one statement in body than these must be enclosed in curly brackets.

So, we got a brief overview of what the heck is lambda expression. Please have patience if you feel lost and not able to relate, how it can be used in java programming language. We will make out everything in next 30 minutes. So let’s get going.

Before going deep in relation between lambda expressions and java programming, you must know about functional interfaces as well. It is just too important.

2. Java 8 functional interface

Single Abstract Method interfaces (SAM Interfaces) is not a new concept. It means interfaces with only one single method. In java, we already have many examples of such SAM interfaces. From java 8, they will also be referred as functional interfaces as well. Java 8, enforces the rule of single responsibility by marking these interfaces with a new annotation i.e. @FunctionalInterface.

For example, new definition of Runnable interface is like this:

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

If you try to add a new method in any functional interface, compiler would not allow you to do this and will throw compile time error.

So far so good. But, how they are related to Lambda expressions? Let’s find out the answer.

We know that Lambda expressions are anonymous functions with no name and they are passed (mostly) to other functions as parameters. Well, in java method parameters always have a type and this type information is looked for to determine which method needs to be called in case of method overloading or even simple method calling. So, basically every lambda expression also must be convertible to some type to be accepted as method parameters. Well, that type in which lambda expressions are converted, are always of functional interface type.

Let’s understand it with an example. If we have to write a thread which will print “howtodoinjava” in console then simplest code will be:

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("howtodoinjava");
    }
}).start();

If we use the lambda expression for this task then code will be :

new Thread(
            () ->   { 
                        System.out.println("My Runnable"); 
                    }
         ).start();

We have also see that Runnable is an functional interface with single method run(). So, when you pass lambda expression to constructor of Thread class, compiler tries to convert the expression into equivalent Runnable code as shown in first code sample. If compiler succeed then everything runs fine, if compiler is not able to convert the expression into equivalent implementation code, it will complain. Here, in above example, lambda expression is converted to type Runnable.In simple words, a lambda expression is an instance of a functional interface. But a lambda expression itself does not contain the information about which functional interface it is implementing; that information is deduced from the context in which it is used.

3. Java 8 lambda expression examples

I am listing out some code samples which you can read and analyze to how a lambda expression can be used in day to day programming.

1) Iterating over a List and perform some operations

List<String> pointList = new ArrayList();
pointList.add("1");
pointList.add("2");
 
pointList.forEach(p ->  {
                            System.out.println(p);
                            //Do more work
                        }
                 );

2) Create a new runnable and pass it to thread

new Thread(
    () -> System.out.println("My Runnable"); 
).start();

3) Sorting employees objects by their name

public class LambdaIntroduction {
 
  public static void main (String[] ar){
          Employee[] employees  = {
              new Employee("David"),
              new Employee("Naveen"),
              new Employee("Alex"),
              new Employee("Richard")};
            
          System.out.println("Before Sorting Names: "+Arrays.toString(employees));
          Arrays.sort(employees, Employee::nameCompare);
          System.out.println("After Sorting Names "+Arrays.toString(employees));
      }
}
  
class Employee {
  String name;
  
  Employee(String name) {
    this.name = name;
  }
  
  public static int nameCompare(Employee a1, Employee a2) {
    return a1.name.compareTo(a2.name);
  }
    
  public String toString() {
    return name;
  }
}
 
Output:
 
Before Sorting Names: [David, Naveen, Alex, Richard]
After Sorting Names [Alex, David, Naveen, Richard]

4) Adding an event listener to a GUI component

JButton button =  new JButton("Submit");
button.addActionListener((e) -> {
    System.out.println("Click event triggered !!");
});   

Above are very basic examples of lambda expressions in java 8. I will be coming up with more useful examples and code samples from time to time.

Happy Learning !!


Leave a Reply

Close Menu