Java 8 – Lambda Expressions

Lambda expression is a very new and exciting feature of Java 8. Lambda style expressions are not unknown to many of us who have worked on advanced languages like Scala.

In this Java tutorial, we will learn about lambda expressions and various concepts around it.

 Table of Contents

1. What is a Lambda Expression in Java?
2. Lambda Expression Syntax
3. Features of Lambda Expressions in Java 8
4. Java 8 Functional Interface
5. Lambda Expression Examples

Let’s stick to the plan and move step by step.

1. What is a Lambda Expression?

In general programming language, a Lambda expression (or function) is an anonymous function, i.e., a function with no name and any identifier.

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 feature 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 the same but results will be different based on different parameters passed to function).

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

Lambda expressions provide many benefits to functional programming over object-oriented programming (OOP). Most OOP languages evolve around classes and objects and these languages treat only the classes as their first-class citizens. The other important entity, i.e. functions, takes the back seat.

This is especially 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, we can define functions, give them reference variables, and pass them as method arguments and much more.

JavaScript is a good example of functional programming where we can pass callback methods to Ajax calls and so on. It is a very useful feature and has been lacking in Java from the beginning. Now with Java 8, we can also use functional programming concepts with the help of lambda expressions.

2. Lambda Expression Syntax

A typical lambda expression syntax will be like this:

(parameters) -> expression

For example, the given lambda expression takes two parameters and returns their addition.

Based on the type of x and y, the expresson will be used differently. If the parameters match to Integer the expression will add the two numbers. If the parameters of type String the expression will concat the two strings.

(x, y) -> x + y		

3. Features of Lambda Expressions in Java 8

  • A lambda expression can have zero, one or more parameters.
  • The type of the parameters can be explicitly declared or it can be inferred from the context.
  • Multiple parameters are enclosed in mandatory parentheses and separated by commas. Empty parentheses are used to represent an empty set of parameters.
    () -> expression
    
    (param1, param2, param3) -> expression
  • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses. e.g. a -> return a*a.
  • The the body of the lambda expressions can contain zero, one or more statements.
  • If the 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 the body than these must be enclosed in curly brackets.
    (parameters) -> { statements; }

So, we got a brief overview of what is a lambda expression. Before going deep in the relation between lambda expressions and Java programming, we must know about Functional Interfaces as well. It is just too important.

4. 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, SAM Interfaces will also be referred to as functional interfaces. 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 we try to add a new method in any functional interface, the compiler would not allow you to do this and will throw compile-time error.

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 the 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, the type in which lambda expressions are converted, are always of functional interface type.

Two good examples of functional interface type are Consumer and BiConsumer interfaces.

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();

The Runnable is a functional interface with a single method run(). So, when we pass a lambda expression to the constructor of Thread class, the compiler tries to convert the expression into equivalent Runnable code as shown in the first code sample.

If the compiler succeeds then everything runs fine. If the compiler is not able to convert the expression into an equivalent implementation code, it will complain. Here, in the above example, the lambda expression is converted to type Runnable.

A lambda expression is an instance of a functional interface but the lambda expression itself does not contain the information about which functional interface it is implementing. This information is deduced from the context in which expression is used.

5. Java 8 Lambda Expression Example

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

Example 1: Using lambda expression to iterate over a List and perform some action on list elements

In the given example, we are iterating over the list and printing all the list elements in the standard output. We can perform any desired operation in place of printing them.

List<String> pointList = new ArrayList();

pointList.add("1");
pointList.add("2");

pointList.forEach(p ->  { System.out.println(p); } );

Example 2: Using lambda expression to create and start a Thread in Java

In given example, we are passing the instance of Runnable interface into the Thread constructor.

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

Example 3: Using lambda expression for 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 !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

18 thoughts on “Java 8 – Lambda Expressions”

  1. Genuinely good article specially the example where you explained how lambda is converted to functional interface with example of Runnable.

    Reply
  2. i want to append “1” to each element. But its not allowing me any reason ?
    i simply replace //do more work with p+”1″; but it is thowing compile error.

    
    List<String> pointList = new ArrayList();
    pointList.add("1");
    pointList.add("2");
     
    pointList.forEach(p ->  {
                                System.out.println(p);
                                //Do more work
                                p+"1";
                            }
                     );
    
    
    Reply
    • Basically, when u are trying to mutate a value in list while iteration, it won’t work as per desired way. So, the best option is a dummy list and play with it like this.

      List pointList = new ArrayList();
      pointList.add("1");
      pointList.add("2");
      List newList = new ArrayList();
      pointList.forEach(e > newList.add(e+1));
      pointList = newList;
      System.out.println(pointList);
      Reply
  3. Hi Lokesh, I am following HTDIJ for long time and I must say that current presentation of the topics is best so far, easy to access.

    Regards, AJ

    Reply
  4. Hi Lokesh

    Just wanted to know if you can also possibly mention what all new api’s have been added in Java 8.
    For example Iterable.foreach has been added recently.

    Reply
  5. while lambda expressions have definitely added to the language feature i.e. doing away with cryptic codes I still have a feeling that they are mere syntactical changes. With my current knowledge of the features of java8 I believe the real action is in streams …. but that is just my opinion 🙂

    Reply
    • You are absolutely right about lambdas. They are basically for making code shorter, cleaner and easy to read (once we are in habit of it). But for providing lambda support, they had to introduce function interfaces, and this is a very much game changer in my opinion. This is going to change a lot the way we write APIs/frameworks today.

      Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.