Java 8 Lambda Expressions Tutorial with Examples

Java is a first-class object-oriented language. With the exception of primitive data types, everything in Java is an object. Even an array is an Object. Every class creates instances that are objects. There is no way of defining just a function / method which stays in Java all by itself. There is no way of passing a method as argument or returning a method body for that instance.

Since the old days of Swing, we always had written anonymous classes if we wanted to pass some functionality to any method. For example the old event listener code used to look like:

someObject.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
                
                //Event listener implementation goes here...
                
            }
        });

Here we wanted to add some custom code to Mouse listener. We defined an anonymous inner class MouseAdapter and created its object. This way we passed some functionality to addMouseListener method.

In short, it is not easy to pass plain methods / functionalities in Java that can be passed as arguments. Due to this limitation Java 8 adds a brand new language level feature called Lambda Expressions.

Why Java needs Lambda Expressions?

Since its beginning, the Java language hasn’t evolved much if you ignore some of the features like Annotations, Generics etc. Mostly during its life Java always remained Object first language. After working with functional language like JavaScript, it becomes clear to one how Java enforce its strict object-oriented nature and strict typed on the source code. You see Functions are not important for Java. On their own they cannot live in Java world.

xkcd-functionalFunctions are first class citizens in a functional programming language. They exists on their own. You can assign them to a variable and pass them as arguments to other functions. JavaScript is one of the best example of an FP language. There are some good articles here and here that clearly describes the benefits of JavaScript as a functional language. A functional language provides very powerful feature called Closure that has quite a few advantages over traditional way of writing applications. A closure is a function or reference to a function together with a referencing environment — a table storing a reference to each of the non-local variables of that function. Closest thing that Java can provide to Closure is Lambda expressions. There is significant difference between a Closure and Lambda expression, but at least Lambda expression provides a good alternative to Closure.

In his quite sarcastic and funny blog post, Steve Yegge describes how Java world is strictly about Nouns. If you haven’t read his blog, go first read it. It’s funny, its interesting and it describe the exact reason why Java had to add Lambda expressions.

Lambda expression adds that missing link of functional programming to Java. Lambda expression let us have functions as first class citizen. Although this is not 100% correct, we will shortly see how Lambda expressions are not closures but they are as much close as we can get to closures. In languages that support first class functions, the type of the lambda expression would be a function; but in Java, the lambda expressions are represented as objects, and so they must be bound to a particular object type known as a functional interface. We will see in detail what Functional interface are.

Here is a nicely written article by Mario Fusco on Why we need Lambda Expression in Java. He explains why a modern programming language must have feature like closures.

Introduction to Lambda Expressions

lambda expressions in javaA lambda expression is an anonymous function (not 100% true for Java but lets assume it for time being). Simply put, it’s a method without a declaration, i.e., access modifier, return value declaration, and name.

It’s a shorthand that allows you to write a method in the same place you are going to use it. Especially useful in places where a method is being used only once, and the method definition is short. It saves you the effort of declaring and writing a separate method to the containing class.

Lambda expressions in Java is usual written using syntax (argument) -> (body). For example:

(arg1, arg2...) -> { body }

(type1 arg1, type2 arg2...) -> { body }

Following are some examples of Lambda expressions.

(int a, int b) -> {  return a + b; }

() -> System.out.println("Hello World");

(String s) -> { System.out.println(s); }

() -> 42

() -> { return 3.1415 };

Structure of Lambda Expressions

Let’s check the structure of lambda expressions.

  • 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. e.g. (int a) is same as just (a)
  • Parameters are enclosed in parentheses and separated by commas. e.g. (a, b) or (int a, int b) or (String a, int b, float c)
  • Empty parentheses are used to represent an empty set of parameters. e.g. () -> 42
  • 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 body of the lambda expressions can contain zero, one or more statements.
  • 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 (a code block) and the return type of the anonymous function is the same as the type of the value returned within the code block, or void if nothing is returned.

What are Functional Interfaces

In Java, a Marker interface is an interface with no methods or fields declaration. In simple words, marker interface is an empty interface. Similarly, a Functional Interface is an interface with just one abstract method declared in it.

java.lang.Runnable is an example of a Functional Interface. There is only one method void run() declared in Runnable interface. Similarly ActionListener interface is also a Functional Interface. We use Anonymous inner classes to instantiate objects of functional interface. With Lambda expressions, this can be simplified.

Each lambda expression can be implicitly assigned to one of the interface called Functional interface. For example we can create Runnable interface’s reference from lambda expression like below:

Runnable r = () -> System.out.println("hello world");

This type of conversion is automatically taken care by compiler when we dont specify the functional interface. For example:

new Thread(
	() -> System.out.println("hello world")
).start();

So in above code, compiler automatically deduced that lambda expression can be casted to Runnable interface from Thread class’s constructor signature public Thread(Runnable r) { }.

Few examples of lambda expressions and their functional interface:

Consumer<Integer>  c = (int x) -> { System.out.println(x) };

BiConsumer<Integer, String> b = (Integer x, String y) -> System.out.println(x + " : " + y);

Predicate<String> p = (String s) -> { s == null };

@FunctionalInterface is a new interface added in Java 8 to indicate that an interface type declaration is intended to be a functional interface as defined by the Java Language Specification. Java 8 also declared number of Functional Interfaces that can be used by Lambda expressions. @FunctionalInterface can be used for compiler level errors when the interface you have annotated is not a valid Functional Interface.

Following is an example of custom defined Functional interface.

@FunctionalInterface
public interface WorkerInterface {

	public void doSomeWork();

}

As its definition says, Functional Interfaces can have only one abstract method. If you try to add one more abstract method in it, it throws compile time error. For example:

@FunctionalInterface
public interface WorkerInterface {

	public void doSomeWork();
	
	public void doSomeMoreWork();

}

Error:

Unexpected @FunctionalInterface annotation 
	@FunctionalInterface ^ WorkerInterface is not a functional interface multiple 
	non-overriding abstract methods found in interface WorkerInterface 1 error

Once the Functional interface is defined, we can simply use it in our API and take advantage of Lambda expressions. For example:

//define a functional interface
@FunctionalInterface
public interface WorkerInterface {

	public void doSomeWork();

}


public class WorkerInterfaceTest {

	public static void execute(WorkerInterface worker) {
		worker.doSomeWork();
	}

	public static void main(String [] args) {

		//invoke doSomeWork using Annonymous class
		execute(new WorkerInterface() {
			@Override
			public void doSomeWork() {
				System.out.println("Worker invoked using Anonymous class");
			}
		});
	
		//invoke doSomeWork using Lambda expression	
		execute( () -> System.out.println("Worker invoked using Lambda expression") );
	}

}

Output:

Worker invoked using Anonymous class 
Worker invoked using Lambda expression

Here we created our own Functional interface and used to with lambda expressions. execute() method can now take lambda expressions as argument.

Examples of Lambda Expression

Best way of learning about Lambda expressions is by examples. Following are few examples:

Thread can be initialized like following:

//Old way:
new Thread(new Runnable() {
	@Override
	public void run() {
		System.out.println("Hello from thread");
	}
}).start();

//New way:
new Thread(
	() -> System.out.println("Hello from thread")
).start();

The event handling can be done with Java 8 using lambda expression. Following code we show both old and new way of adding ActionListener to a UI component.

//Old way:
button.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent e) {
		System.out.println("The button was clicked using old fashion code!");
	}
});

//New way:
button.addActionListener( (e) -> {
		System.out.println("The button was clicked. From lambda expressions !");
});

Simple code to print all elements of given array. Note there is one more way of using lambda expression. In below example we use the usual way of creating lambda expression using arrow syntax and also we used a brand new double colon (::) operator that Java 8 has to convert a normal method into lambda expression.

//Old way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
for(Integer n: list) {
	System.out.println(n);
}

//New way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
list.forEach(n -> System.out.println(n));


//or we can use :: double colon operator in Java 8
list.forEach(System.out::println);

In this example we use Predicate functional interface to create a test and print the elements that pass the test. This way you can provide the logic using lambda expression and do something based on it.

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Main {
  
	public static void main(String [] a)  {

		List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

		System.out.println("Print all numbers:");
		evaluate(list, (n)->true);

		System.out.println("Print no numbers:");
		evaluate(list, (n)->false);

		System.out.println("Print even numbers:");
		evaluate(list, (n)-> n%2 == 0 );

		System.out.println("Print odd numbers:");
		evaluate(list, (n)-> n%2 == 1 );

		System.out.println("Print numbers greater than 5:");
		evaluate(list, (n)-> n > 5 );

	}

	public static void evaluate(List<Integer> list, Predicate<Integer> predicate) {
		for(Integer n: list)  {
			if(predicate.test(n)) {
				System.out.println(n + " ");
			}
		}
	}

}

Output:

Print all numbers: 1 2 3 4 5 6 7 
Print no numbers: 
Print even numbers: 2 4 6 
Print odd numbers: 1 3 5 7 
Print numbers greater than 5: 6 7

Some wizardry using Lambda expression to print square of each element of a list. Notice we used .stream() method to convert regular list into a steam. Java 8 added some awesome Stream APIs. java.util.stream.Stream interface comes with tons of useful methods which can be used along with lambda expression to do some voodoo. We passed a lambda expression x -> x*x to map() method which applies this to all elements of the stream. After that we use forEach to print the all elements of list.

//Old way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
for(Integer n : list) {
	int x = n * n;
	System.out.println(x);
}

//New way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
list.stream().map((x) -> x*x).forEach(System.out::println);

Given a list, sum the square of each element from this list. See how Lambda expression can be used to achieve this in a single statement. This is also a starters example on MapReduce. We used map() to square each element and then reduce() to reduce all elements into single number.

//Old way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = 0;
for(Integer n : list) {
	int x = n * n;
	sum = sum + x;
}
System.out.println(sum);

//New way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();
System.out.println(sum);

Difference between Lambda Expression and Anonymous class

One key difference between using Anonymous class and Lambda expression is the use of this keyword. For anonymous class ‘this’ keyword resolves to anonymous class, whereas for lambda expression ‘this’ keyword resolves to enclosing class where lambda is written.

Another difference between lambda expression and anonymous class is in the way these two are compiled. Java compiler compiles lambda expressions and convert them into private method of the class. It uses invokedynamic instruction that was added in Java 7 to bind this method dynamically. Tal Weiss has written a good blog on how Java compiles the lambda expressions into bytecode.

That’s All Folks

Mark Reinhold, Oracle’s Chief Architect, describes Lambda expressions as the single largest upgrade to the programming model ever — larger even than generics. And why not. It gives Java programmer the edge that it lacked compared to other functional programming languages. Along with other features like Virtual extension methods, Lambda expression can be utilized to write some really good code.

I hope this article gave a glimpse of what’s in the store for us in Java 8. Ciao :)

Image courtesy:

Get our Articles via Email. Enter your email address.

You may also like...

74 Comments

  1. GT says:

    Fantastic blog Viral … very comprehensive and covers all the aspects starting from scratch….

    regards,
    Anil

  2. Pankaj says:

    Thanks Viral for brief explaination.
    This was very much awaited feature in Java.

  3. Gagan Chamria says:

    very useful for everybody.

  4. Kuntal says:

    I believe the most pressing reason for including “Closure”s into Java platform is that they make it easier to distribute processing of collections over multiple threads. Currently, lists and sets are typically processed by client code obtaining an iterator from the collection, then using that to iterate over its elements and process each in turn. If the processing of different elements is to proceed in parallel, it is the responsibility of the client code, not the collection, to organize this.
    In Java 8, the intention is instead to provide collections with methods that will take functions and use them, each in different ways, to process their elements. The advantage that this change brings is that collections can now organize their own iteration internally, transferring responsibility for parallel-ization from client code into library code.

  5. Amit says:

    Nice….Carry on Viral

  6. Viraf Karai says:

    Very well-written. I enjoyed reading this article. I will use the pointers and tips outlined here when I use Java 8 (hopefully soon).

  7. Brameshmadhav says:

    Excellent read this… Lambda in… Now Java takes on Node head on head…

    Thanks Viral… Again good read…

  8. SoftMAS Desarrollo de software says:

    Nice!!, very good explained, thanks a lot.

  9. Gopinathan K M says:

    Dear Viral

    Well wriiten, These are the precise reason why Clojure? Another JVM language and why we need to take hard look at it.

    Regards
    Gopinathan K M

  10. Reuben John says:

    Really great blog! Just made the shift from C++ to Java here and I haven’t written a word of Java yet and this blog makes complete sense! Lambda expressions are exhilarating and I can’t wait to start coding. Well written. Well Done.

  11. Sumit says:

    How i run my lambda expression in eclipse with java8 , i donot have compiler 1.8 in my sts 3.4.0 Please suggest me solution on this! else a eclipse link which has java8 comptabile

  12. kunal says:

    Nice Post bro very impressive work

  13. Krueker says:

    Really great introduction but I still have a question: why?
    Do lambda expressions add any performance increases
    or are they only good for impressing coworkers and confusing
    new comers? I don’t see how they’d make reading code any
    simpler and much, like the ternary operator, could just add
    to unreadability….

  14. Really great introduction but I still have a question: why?
    Do lambda expressions add any performance increases
    or are they only good for impressing coworkers and confusing
    new comers?

  15. Salim says:

    Excellent non agressive introduction to lambda expressions in Java.
    Thank you so much

  16. Mudassir says:

    Good read. Nicely explained. Thumbs up for the effort put.

  17. Raman says:

    Thanks

  18. Robert says:

    Lambdas are a great addition to Java. Thank you for describing it.

  19. Panagiotis says:

    Excellent post! – Thank you very much

  20. Preeti Khunteta says:

    Good description of lambda expressions…Thanks

  21. Pravin Kumar says:

    List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

    System.out.println(“Print all numbers:”);
    evaluate(list, (n)->true);

    In the example (n) -> true; you are calling the method by passing the argument as n but from where value came for n there is not indication that you accessing the list and putting the value in n………………..
    I am not clear with the can u clear me?????

  22. Critical Ken says:

    I still don’t really get the exact use of this….We can still achieve this using the “normal” java way to provide an implementation to the method and calling it. What is the value add in introducing this new (- >) wierd syntax and making the code all the more confusing?

  23. Pegasus99 says:

    Very helpful thanks a lot

  24. Pedro says:

    >Critical Ken
    Java has to come with something new-age to compete with new languages like Scala and to attract new developers.
    I agree with you i think the lambda expressions are COMPLETELY useless and makes the code much harder to read specially on enterprise application with thousands of lines.

    • Ravi Bonala says:

      good feature and nice explanation

    • Vijay says:

      …I totally agree with you.
      This article, well written but misses the point though.

  25. Shanthakumar says:

    Good post to get started :)

  26. Thank you very much. Very googd explanation!

  27. Naimo says:

    Argh, at last! C# fanboys lost their “main argument” that “Java doesn’t have lambdas” :) Now Java has all the same stuff as C#, but is far better. Moreover Java doesn’t have crappy stuff like “extension methods” or “var” and “dynamic” that makes the code completely obfuscated and hard to understand. High five!

    • Mohammad says:

      It’s very easy to judge something when you have just no clue about. Java has stolen many features from C# including lambda expressions which we have been using it for over 5 years now :)

      • Osman Bakri says:

        The idea, first, is not from C#, they also stole it from another language!! , second it is useless!! What the value of decrease my code 2 lines and make it harder to understand.

        • Kunal says:

          This has no value add and it only introduces complicated way of coding things and new expressions like this is difficult to understand.

          Thanks for sharring

          Regards

          Kunal Shahg

          • bioo says:

            hi

  28. Sreeju says:

    Beautiful article.. Helped me get started with lambda expressions within 10 minutes Thanks a lot..

  29. shohan says:

    Thanks a lot for nice article.

    Compilation fail: Consumer c = (int x) -> { System.out.println(x) }; but Consumer c = (Integer x) -> { System.out.println(x); }; it works for mine.

    • Vraj Pandya says:

      the int is a primitive type and the Integer is a class well defined in java.lang

      The consumer interface is generically declared.
      The declaration is done this way:

      public interface Consumer&lt;T&gt;

      So, just like ArrayList it need an object so it can apply the operation it needs to perform.

      all in all, int is not a class while Integer is.

  30. groovy says:

    Will this make some scripting language obsolete?

  31. Pankaj Lilhare says:

    Great Job Viral!
    Very impressive blog… Thanks

  32. Kammiti Krishna says:

    Without people like you we cannot survive in technology.

  33. Matt Trousdale says:

    Nice easy to follow artical thanks. However I have been programming in Java (and other langs) for 17 years – freelance for around 7. I believe the reason, as at least one person has hinted at here, the reason Java has stayed away from the functional arena is because it was well known 20 + years ago that funtional lang were not great for large biz applications, maybe this fundament has change over time but I doubt it seeing how difficult people are finding large changes in some big MVVM applications.

    This is a reference to the sarcastic blog. I hope I never work on a huge application that guy’s in charge of.

    My feeling, speaking from real world experience rather than a position of athority is –

    Horses for courses.

  34. Kavya says:

    Very informative article with clearly explained examples and relative links.

  35. Ramakrishnan R says:

    This has no value add and it only introduces complicated way of coding things and new expressions like this is difficult to understand.

  36. such a useful information, thanks a lot.

  37. DV says:

    Thanks for this , this was very helpful. However if you have a number of values to evaluate in for loop and using the result of them how can it be done in Java 8 ?

    int gridSize = 20;
    		long paths = 1;
    		for (int i = 0; i &lt; gridSize; i++) {
    			paths *= (2 * gridSize) - i; 
    			paths /= i + 1;
    		}
    		System.out.println(paths);
    
  38. Eugene K says:

    Great Article! Thank you!

  39. Peter says:

    I’m trying to learn lambdas and i’ve pasted these examples lambdas in but none of them seems to work.

    (int a, int b) -> { return a + b; }
    () -> System.out.println(“Hello World”);
    (String s) -> { System.out.println(s); }
    () -> 42

    () -> { return 3.1415 };

    • Peter says:

      I get a
      Multiple markers at this line
      – Syntax error, insert “AssignmentOperator Expression” to complete Assignment
      – Syntax error, insert “;” to complete Statement

  40. Ankur Dadoo says:

    Amazing tutorial – I read so many tutorials but the way you laid out the basic rules helped me understand what Lambda is all about and how it works – Thank you for this great tutorial

  41. Anshudeep says:

    True power of Lambda expression lies in its use in parallel computing with Stream API. Ofcourse it does solve vertical problem and make the code compact and readable. People will get some time getting use to functional programming in Java.

  42. Sandya Reddy Madireddy says:

    Good Article Viral. Thanks for your work.

  43. Hari Polisetty says:

    By far the best explanation I have seen of Lambda functions.
    I’ve a lot of dev experience but a short attention span, so it was difficult for me to figure out how lambda functions figure our the binding to the correct interface method, until I read this article where it describes the connection between lambda functions and functional interfaces.

  44. Nisha says:

    This is really nice article. I have a query as while defining an interface can we use varargs for specifying the arguments. I tried to do so but getting compilation error as it is referring to arrays & not varargs. The example I am trying for is as below
    public interface Polygon{
    public double calcArea(double… s);
    }
    With varargs I will get a flexibility to use this for polygons with different number of sides.

  45. Ashish Patel says:

    Very Good Material

  46. JenyaKirmiza says:

    Can you help me to convert this piece of code to lambda:

    obs.subscribe(new Observer<List>() {
    public void onCompleted() {
    System.out.println(“completed”);
    }

    public void onError(Throwable e) {
    System.out.println(“failure”);
    }

    public void onNext(List value) {
    System.out.println(“onnext=” + value);
    }
    });
    to

  47. Venu says:

    Awesome explanation and great examples taken. I loved the article. Thanks Viral

  48. TN Subramaniam says:

    I have read a lot on Java 8 lambdas. This is the simplest introduction I can recommend. Very good

  49. Tomás says:

    Amazing article. This is the first article after which I really have a basic understanding of how lambda expressions work. Especially after the functional interface method.

    Thank you Viral! :)

  50. Tomás says:

    Amazing article. This is the first article after which I really have a basic understanding of how lambda expressions work. Especially after the functional interface explenation.

    Thank you Viral! :)

  51. Naveen says:

    Good Explanation .Loved It The way You Presented .

  52. sandeep tengale says:

    Nice tutorial, Thank you :)

  53. DJ says:

    This post was very helpful, but at the same time angered me: You use MouseAdapter as your very FIRST example, but did not follow up saying how to turn that into a lambda (if possible)

  54. DB says:

    Great article Viral. I particularly like the examples you have provided.

  55. Swastik says:

    Nice explanation. Simple and concise

  56. sriram says:

    Easily understandable with great examples with older version code comparison.

  57. Prashant K says:

    Great explanation by Viral. Keep it up.

  58. David says:

    Lambda expression facilitates functional programming, and simplifies the development a lot, that is the biggest power of Java 8.

    Great tutorial. Keep going on.

  59. neha says:

    This is the simplest explanation of lambda expression I have read so far.

  60. andy says:

    This is really helpful. Thanks a lot!

  61. Ameya Patil says:

    Absolutely spendid, you have an ‘ART’ of teaching ! Best article I have read on internet. Keep up great work

  62. Sadiq says:

    Great job covering this topic in such a simple manner. Kudos! Keep up the good work.

  63. David He says:

    nice article

  64. Carol says:

    Very good article. Thanks!

  65. Kiran says:

    Great article. Thank you!

Leave a Reply

Your email address will not be published. Required fields are marked *