The Java Tutorials have been written for JDK 8. Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available. See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases. See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.

Lambda Expressions

One issue with anonymous classes is that if the implementation of your anonymous class is very simple, such as an interface that contains only one method, then the syntax of anonymous classes may seem unwieldy and unclear. In these cases, you're usually trying to pass functionality as an argument to another method, such as what action should be taken when someone clicks a button. Lambda expressions enable you to do this, to treat functionality as method argument, or code as data.

The previous section, Anonymous Classes , shows you how to implement a base class without giving it a name. Although this is often more concise than a named class, for classes with only one method, even an anonymous class seems a bit excessive and cumbersome. Lambda expressions let you express instances of single-method classes more compactly.

This section covers the following topics:

Approach 1: Create Methods That Search for Members That Match One Characteristic

Approach 2: create more generalized search methods, approach 3: specify search criteria code in a local class, approach 4: specify search criteria code in an anonymous class, approach 5: specify search criteria code with a lambda expression, approach 6: use standard functional interfaces with lambda expressions, approach 7: use lambda expressions throughout your application, approach 8: use generics more extensively, approach 9: use aggregate operations that accept lambda expressions as parameters, lambda expressions in gui applications, syntax of lambda expressions, accessing local variables of the enclosing scope, target types and method arguments, serialization, ideal use case for lambda expressions.

Suppose that you are creating a social networking application. You want to create a feature that enables an administrator to perform any kind of action, such as sending a message, on members of the social networking application that satisfy certain criteria. The following table describes this use case in detail:

Field Description
Name Perform action on selected members
Primary Actor Administrator
Preconditions Administrator is logged in to the system.
Postconditions Action is performed only on members that fit the specified criteria.
Main Success Scenario button.
Extensions

1a. Administrator has an option to preview those members who match the specified criteria before he or she specifies the action to be performed or before selecting the button.

Frequency of Occurrence Many times during the day.

Suppose that members of this social networking application are represented by the following Person class:

Suppose that the members of your social networking application are stored in a List<Person> instance.

This section begins with a naive approach to this use case. It improves upon this approach with local and anonymous classes, and then finishes with an efficient and concise approach using lambda expressions. Find the code excerpts described in this section in the example RosterTest .

One simplistic approach is to create several methods; each method searches for members that match one characteristic, such as gender or age. The following method prints members that are older than a specified age:

Note : A List is an ordered Collection . A collection is an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. For more information about collections, see the Collections trail.

This approach can potentially make your application brittle , which is the likelihood of an application not working because of the introduction of updates (such as newer data types). Suppose that you upgrade your application and change the structure of the Person class such that it contains different member variables; perhaps the class records and measures ages with a different data type or algorithm. You would have to rewrite a lot of your API to accommodate this change. In addition, this approach is unnecessarily restrictive; what if you wanted to print members younger than a certain age, for example?

The following method is more generic than printPersonsOlderThan ; it prints members within a specified range of ages:

What if you want to print members of a specified sex, or a combination of a specified gender and age range? What if you decide to change the Person class and add other attributes such as relationship status or geographical location? Although this method is more generic than printPersonsOlderThan , trying to create a separate method for each possible search query can still lead to brittle code. You can instead separate the code that specifies the criteria for which you want to search in a different class.

The following method prints members that match search criteria that you specify:

This method checks each Person instance contained in the List parameter roster whether it satisfies the search criteria specified in the CheckPerson parameter tester by invoking the method tester.test . If the method tester.test returns a true value, then the method printPersons is invoked on the Person instance.

To specify the search criteria, you implement the CheckPerson interface:

The following class implements the CheckPerson interface by specifying an implementation for the method test . This method filters members that are eligible for Selective Service in the United States: it returns a true value if its Person parameter is male and between the ages of 18 and 25:

To use this class, you create a new instance of it and invoke the printPersons method:

Although this approach is less brittle—you don't have to rewrite methods if you change the structure of the Person —you still have additional code: a new interface and a local class for each search you plan to perform in your application. Because CheckPersonEligibleForSelectiveService implements an interface, you can use an anonymous class instead of a local class and bypass the need to declare a new class for each search.

One of the arguments of the following invocation of the method printPersons is an anonymous class that filters members that are eligible for Selective Service in the United States: those who are male and between the ages of 18 and 25:

This approach reduces the amount of code required because you don't have to create a new class for each search that you want to perform. However, the syntax of anonymous classes is bulky considering that the CheckPerson interface contains only one method. In this case, you can use a lambda expression instead of an anonymous class, as described in the next section.

The CheckPerson interface is a functional interface . A functional interface is any interface that contains only one abstract method . (A functional interface may contain one or more default methods or static methods .) Because a functional interface contains only one abstract method, you can omit the name of that method when you implement it. To do this, instead of using an anonymous class expression, you use a lambda expression , which is highlighted in the following method invocation:

See Syntax of Lambda Expressions for information about how to define lambda expressions.

You can use a standard functional interface in place of the interface CheckPerson , which reduces even further the amount of code required.

Reconsider the CheckPerson interface:

This is a very simple interface. It's a functional interface because it contains only one abstract method. This method takes one parameter and returns a boolean value. The method is so simple that it might not be worth it to define one in your application. Consequently, the JDK defines several standard functional interfaces, which you can find in the package java.util.function .

For example, you can use the Predicate<T> interface in place of CheckPerson . This interface contains the method boolean test(T t) :

The interface Predicate<T> is an example of a generic interface. (For more information about generics, see the Generics (Updated) lesson.) Generic types (such as generic interfaces) specify one or more type parameters within angle brackets ( <> ). This interface contains only one type parameter, T . When you declare or instantiate a generic type with actual type arguments, you have a parameterized type. For example, the parameterized type Predicate<Person> is the following:

This parameterized type contains a method that has the same return type and parameters as CheckPerson.boolean test(Person p) . Consequently, you can use Predicate<T> in place of CheckPerson as the following method demonstrates:

As a result, the following method invocation is the same as when you invoked printPersons in Approach 3: Specify Search Criteria Code in a Local Class to obtain members who are eligible for Selective Service:

This is not the only possible place in this method to use a lambda expression. The following approach suggests other ways to use lambda expressions.

Reconsider the method printPersonsWithPredicate to see where else you could use lambda expressions:

This method checks each Person instance contained in the List parameter roster whether it satisfies the criteria specified in the Predicate parameter tester . If the Person instance does satisfy the criteria specified by tester , the method printPerson is invoked on the Person instance.

Instead of invoking the method printPerson , you can specify a different action to perform on those Person instances that satisfy the criteria specified by tester . You can specify this action with a lambda expression. Suppose you want a lambda expression similar to printPerson , one that takes one argument (an object of type Person ) and returns void. Remember, to use a lambda expression, you need to implement a functional interface. In this case, you need a functional interface that contains an abstract method that can take one argument of type Person and returns void. The Consumer<T> interface contains the method void accept(T t) , which has these characteristics. The following method replaces the invocation p.printPerson() with an instance of Consumer<Person> that invokes the method accept :

As a result, the following method invocation is the same as when you invoked printPersons in Approach 3: Specify Search Criteria Code in a Local Class to obtain members who are eligible for Selective Service. The lambda expression used to print members is highlighted:

What if you want to do more with your members' profiles than printing them out. Suppose that you want to validate the members' profiles or retrieve their contact information? In this case, you need a functional interface that contains an abstract method that returns a value. The Function<T,R> interface contains the method R apply(T t) . The following method retrieves the data specified by the parameter mapper , and then performs an action on it specified by the parameter block :

The following method retrieves the email address from each member contained in roster who is eligible for Selective Service and then prints it:

Reconsider the method processPersonsWithFunction . The following is a generic version of it that accepts, as a parameter, a collection that contains elements of any data type:

To print the e-mail address of members who are eligible for Selective Service, invoke the processElements method as follows:

This method invocation performs the following actions:

  • Obtains a source of objects from the collection source . In this example, it obtains a source of Person objects from the collection roster . Notice that the collection roster , which is a collection of type List , is also an object of type Iterable .
  • Filters objects that match the Predicate object tester . In this example, the Predicate object is a lambda expression that specifies which members would be eligible for Selective Service.
  • Maps each filtered object to a value as specified by the Function object mapper . In this example, the Function object is a lambda expression that returns the e-mail address of a member.
  • Performs an action on each mapped object as specified by the Consumer object block . In this example, the Consumer object is a lambda expression that prints a string, which is the e-mail address returned by the Function object.

You can replace each of these actions with an aggregate operation.

The following example uses aggregate operations to print the e-mail addresses of those members contained in the collection roster who are eligible for Selective Service:

The following table maps each of the operations the method processElements performs with the corresponding aggregate operation:

Action Aggregate Operation
Obtain a source of objects ()
Filter objects that match a object (Predicate<? super T> predicate)
Map objects to another value as specified by a object (Function<? super T,? extends R> mapper)
Perform an action as specified by a object (Consumer<? super T> action)

The operations filter , map , and forEach are aggregate operations . Aggregate operations process elements from a stream, not directly from a collection (which is the reason why the first method invoked in this example is stream ). A stream is a sequence of elements. Unlike a collection, it is not a data structure that stores elements. Instead, a stream carries values from a source, such as collection, through a pipeline. A pipeline is a sequence of stream operations, which in this example is filter - map - forEach . In addition, aggregate operations typically accept lambda expressions as parameters, enabling you to customize how they behave.

For a more thorough discussion of aggregate operations, see the Aggregate Operations lesson.

To process events in a graphical user interface (GUI) application, such as keyboard actions, mouse actions, and scroll actions, you typically create event handlers, which usually involves implementing a particular interface. Often, event handler interfaces are functional interfaces; they tend to have only one method.

In the JavaFX example HelloWorld.java (discussed in the previous section Anonymous Classes ), you can replace the highlighted anonymous class with a lambda expression in this statement:

The method invocation btn.setOnAction specifies what happens when you select the button represented by the btn object. This method requires an object of type EventHandler<ActionEvent> . The EventHandler<ActionEvent> interface contains only one method, void handle(T event) . This interface is a functional interface, so you could use the following highlighted lambda expression to replace it:

A lambda expression consists of the following:

A comma-separated list of formal parameters enclosed in parentheses. The CheckPerson.test method contains one parameter, p , which represents an instance of the Person class.

Note : You can omit the data type of the parameters in a lambda expression. In addition, you can omit the parentheses if there is only one parameter. For example, the following lambda expression is also valid:

The arrow token, ->

A body, which consists of a single expression or a statement block. This example uses the following expression:

If you specify a single expression, then the Java runtime evaluates the expression and then returns its value. Alternatively, you can use a return statement:

A return statement is not an expression; in a lambda expression, you must enclose statements in braces ( {} ). However, you do not have to enclose a void method invocation in braces. For example, the following is a valid lambda expression:

Note that a lambda expression looks a lot like a method declaration; you can consider lambda expressions as anonymous methods—methods without a name.

The following example, Calculator , is an example of lambda expressions that take more than one formal parameter:

The method operateBinary performs a mathematical operation on two integer operands. The operation itself is specified by an instance of IntegerMath . The example defines two operations with lambda expressions, addition and subtraction . The example prints the following:

Like local and anonymous classes, lambda expressions can capture variables ; they have the same access to local variables of the enclosing scope. However, unlike local and anonymous classes, lambda expressions do not have any shadowing issues (see Shadowing for more information). Lambda expressions are lexically scoped. This means that they do not inherit any names from a supertype or introduce a new level of scoping. Declarations in a lambda expression are interpreted just as they are in the enclosing environment. The following example, LambdaScopeTest , demonstrates this:

This example generates the following output:

If you substitute the parameter x in place of y in the declaration of the lambda expression myConsumer , then the compiler generates an error:

The compiler generates the error "Lambda expression's parameter x cannot redeclare another local variable defined in an enclosing scope" because the lambda expression does not introduce a new level of scoping. Consequently, you can directly access fields, methods, and local variables of the enclosing scope. For example, the lambda expression directly accesses the parameter x of the method methodInFirstLevel . To access variables in the enclosing class, use the keyword this . In this example, this.x refers to the member variable FirstLevel.x .

However, like local and anonymous classes, a lambda expression can only access local variables and parameters of the enclosing block that are final or effectively final. In this example, the variable z is effectively final; its value is never changed after it's initialized. However, suppose that you add the following assignment statement in the the lambda expression myConsumer :

Because of this assignment statement, the variable z is not effectively final anymore. As a result, the Java compiler generates an error message similar to "Local variable z defined in an enclosing scope must be final or effectively final".

Target Typing

How do you determine the type of a lambda expression? Recall the lambda expression that selected members who are male and between the ages 18 and 25 years:

This lambda expression was used in the following two methods:

public static void printPersons(List<Person> roster, CheckPerson tester) in Approach 3: Specify Search Criteria Code in a Local Class

public void printPersonsWithPredicate(List<Person> roster, Predicate<Person> tester) in Approach 6: Use Standard Functional Interfaces with Lambda Expressions

When the Java runtime invokes the method printPersons , it's expecting a data type of CheckPerson , so the lambda expression is of this type. However, when the Java runtime invokes the method printPersonsWithPredicate , it's expecting a data type of Predicate<Person> , so the lambda expression is of this type. The data type that these methods expect is called the target type . To determine the type of a lambda expression, the Java compiler uses the target type of the context or situation in which the lambda expression was found. It follows that you can only use lambda expressions in situations in which the Java compiler can determine a target type:

Variable declarations

Assignments

Return statements

Array initializers

Method or constructor arguments

Lambda expression bodies

Conditional expressions, ?:

Cast expressions

For method arguments, the Java compiler determines the target type with two other language features: overload resolution and type argument inference.

Consider the following two functional interfaces ( java.lang.Runnable and java.util.concurrent.Callable<V> ):

The method Runnable.run does not return a value, whereas Callable<V>.call does.

Suppose that you have overloaded the method invoke as follows (see Defining Methods for more information about overloading methods):

Which method will be invoked in the following statement?

The method invoke(Callable<T>) will be invoked because that method returns a value; the method invoke(Runnable) does not. In this case, the type of the lambda expression () -> "done" is Callable<T> .

You can serialize a lambda expression if its target type and its captured arguments are serializable. However, like inner classes , the serialization of lambda expressions is strongly discouraged.

About Oracle | Contact Us | Legal Notices | Terms of Use | Your Privacy Rights

Copyright © 1995, 2022 Oracle and/or its affiliates. All rights reserved.

Learn Java practically and Get Certified .

Popular Tutorials

Popular examples, reference materials, learn java interactively, java introduction.

  • Get Started With Java
  • Your First Java Program
  • Java Comments

Java Fundamentals

  • Java Variables and Literals
  • Java Data Types (Primitive)
  • Java Operators
  • Java Basic Input and Output
  • Java Expressions, Statements and Blocks

Java Flow Control

  • Java if...else Statement
  • Java Ternary Operator
  • Java for Loop
  • Java for-each Loop
  • Java while and do...while Loop
  • Java break Statement
  • Java continue Statement
  • Java switch Statement
  • Java Arrays
  • Java Multidimensional Arrays
  • Java Copy Arrays

Java OOP(I)

  • Java Class and Objects
  • Java Methods
  • Java Method Overloading
  • Java Constructors
  • Java Static Keyword
  • Java Strings
  • Java Access Modifiers
  • Java this Keyword
  • Java final keyword
  • Java Recursion
  • Java instanceof Operator

Java OOP(II)

  • Java Inheritance
  • Java Method Overriding
  • Java Abstract Class and Abstract Methods

Java Interface

  • Java Polymorphism
  • Java Encapsulation

Java OOP(III)

  • Java Nested and Inner Class
  • Java Nested Static Class
  • Java Anonymous Class
  • Java Singleton Class
  • Java enum Constructor
  • Java enum Strings
  • Java Reflection
  • Java Package
  • Java Exception Handling
  • Java Exceptions
  • Java try...catch
  • Java throw and throws
  • Java catch Multiple Exceptions
  • Java try-with-resources
  • Java Annotations
  • Java Annotation Types
  • Java Logging
  • Java Assertions
  • Java Collections Framework
  • Java Collection Interface
  • Java ArrayList
  • Java Vector
  • Java Stack Class
  • Java Queue Interface
  • Java PriorityQueue
  • Java Deque Interface
  • Java LinkedList
  • Java ArrayDeque
  • Java BlockingQueue
  • Java ArrayBlockingQueue
  • Java LinkedBlockingQueue
  • Java Map Interface
  • Java HashMap
  • Java LinkedHashMap
  • Java WeakHashMap
  • Java EnumMap
  • Java SortedMap Interface
  • Java NavigableMap Interface
  • Java TreeMap
  • Java ConcurrentMap Interface
  • Java ConcurrentHashMap
  • Java Set Interface
  • Java HashSet Class
  • Java EnumSet
  • Java LinkedHashSet
  • Java SortedSet Interface
  • Java NavigableSet Interface
  • Java TreeSet
  • Java Algorithms

Java Iterator Interface

  • Java ListIterator Interface

Java I/o Streams

  • Java I/O Streams
  • Java InputStream Class
  • Java OutputStream Class
  • Java FileInputStream Class
  • Java FileOutputStream Class
  • Java ByteArrayInputStream Class
  • Java ByteArrayOutputStream Class
  • Java ObjectInputStream Class
  • Java ObjectOutputStream Class
  • Java BufferedInputStream Class
  • Java BufferedOutputStream Class
  • Java PrintStream Class

Java Reader/Writer

  • Java File Class
  • Java Reader Class
  • Java Writer Class
  • Java InputStreamReader Class
  • Java OutputStreamWriter Class
  • Java FileReader Class
  • Java FileWriter Class
  • Java BufferedReader
  • Java BufferedWriter Class
  • Java StringReader Class
  • Java StringWriter Class
  • Java PrintWriter Class

Additional Topics

  • Java Keywords and Identifiers
  • Java Operator Precedence
  • Java Bitwise and Shift Operators
  • Java Scanner Class
  • Java Type Casting
  • Java Wrapper Class
  • Java autoboxing and unboxing

Java Lambda Expressions

  • Java Generics
  • Nested Loop in Java
  • Java Command-Line Arguments

Java Tutorials

Java HashMap forEach()

Java ArrayList forEach()

  • Java enum Inheritance and Interface

The lambda expression was introduced first time in Java 8. Its main objective to increase the expressive power of the language.

But, before getting into lambdas, we first need to understand functional interfaces.

  • What is Functional Interface?

If a Java interface contains one and only one abstract method then it is termed as functional interface. This only one method specifies the intended purpose of the interface.

For example, the Runnable interface from package java.lang ; is a functional interface because it constitutes only one method i.e. run() .

Example 1: Define a Functional Interface in java

In the above example, the interface MyInterface has only one abstract method getValue(). Hence, it is a functional interface.

Here, we have used the annotation @FunctionalInterface . The annotation forces the Java compiler to indicate that the interface is a functional interface. Hence, does not allow to have more than one abstract method. However, it is not compulsory though.

In Java 7, functional interfaces were considered as Single Abstract Method s or SAM type. SAMs were commonly implemented with Anonymous Classes in Java 7.

Example 2: Implement SAM with anonymous classes in java

Here, we can pass an anonymous class to a method. This helps to write programs with fewer codes in Java 7. However, the syntax was still difficult and a lot of extra lines of code were required.

Java 8 extended the power of a SAMs by going a step further. Since we know that a functional interface has just one method, there should be no need to define the name of that method when passing it as an argument. Lambda expression allows us to do exactly that.

Introduction to lambda expressions

Lambda expression is, essentially, an anonymous or unnamed method. The lambda expression does not execute on its own. Instead, it is used to implement a method defined by a functional interface.

How to define lambda expression in Java?

Here is how we can define lambda expression in Java.

The new operator ( -> ) used is known as an arrow operator or a lambda operator. The syntax might not be clear at the moment. Let's explore some examples,

Suppose, we have a method like this:

We can write this method using lambda expression as:

Here, the method does not have any parameters. Hence, the left side of the operator includes an empty parameter. The right side is the lambda body that specifies the action of the lambda expression. In this case, it returns the value 3.1415.

  • Types of Lambda Body

In Java, the lambda body is of two types.

1. A body with a single expression

This type of lambda body is known as the expression body.

2. A body that consists of a block of code.

This type of the lambda body is known as a block body. The block body allows the lambda body to include multiple statements. These statements are enclosed inside the braces and you have to add a semi-colon after the braces.

Note : For the block body, you can have a return statement if the body returns a value. However, the expression body does not require a return statement.

  • Example 3: Lambda Expression

Let's write a Java program that returns the value of Pi using the lambda expression.

As mentioned earlier, a lambda expression is not executed on its own. Rather, it forms the implementation of the abstract method defined by the functional interface.

So, we need to define a functional interface first.

In the above example,

  • We have created a functional interface named MyInterface . It contains a single abstract method named getPiValue()
  • Inside the Main class, we have declared a reference to MyInterface . Note that we can declare a reference of an interface but we cannot instantiate an interface. That is, // it will throw an error MyInterface ref = new myInterface(); // it is valid MyInterface ref;
  • We then assigned a lambda expression to the reference. ref = () -> 3.1415;
  • Finally, we call the method getPiValue() using the reference interface. When System.out.println("Value of Pi = " + ref.getPiValue());
  • Lambda Expressions with parameters

Till now we have created lambda expressions without any parameters. However, similar to methods , lambda expressions can also have parameters. For example,

Here, the variable n inside the parenthesis is a parameter passed to the lambda expression. The lambda body takes the parameter and checks if it is even or odd.

Example 4: Using lambda expression with parameters

  • Generic Functional Interface

Till now we have used the functional interface that accepts only one type of value. For example,

The above functional interface only accepts String and returns String . However, we can make the functional interface generic, so that any data type is accepted. If you are not sure about generics, visit Java Generics .

Example 5: Generic Functional Interface and Lambda Expressions

In the above example, we have created a generic functional interface named GenericInterface . It contains a generic method named func() .

Here, inside the Main class,

  • GenericInterface<String> reverse - creates a reference to the interface. The interface now operates on String type of data.
  • GenericInterface<Integer> factorial - creates a reference to the interface. The interface, in this case, operates on the Integer type of data.
  • Lambda Expression and Stream API

The new java.util.stream package has been added to JDK8, which allows Java developers to perform operations like search, filter, map, reduce, or manipulate collections like Lists.

For example, we have a stream of data (in our case, a List of String ) where each string is a combination of the country name and place of the country. Now, we can process this stream of data and retrieve only the places from Nepal.

For this, we can perform bulk operations in the stream by the combination of Stream API and Lambda expression.

Example 6: Demonstration of using lambdas with the Stream API

In the above example, notice the statement

Here, we are using the methods like filter() , map() and forEach() of the Stream API. These methods can take a lambda expression as input.

We can also define our own expressions based on the syntax we learned above. This allows us to reduce the lines of code drastically as we saw in the above example.

Table of Contents

  • Introduction to lambda expression

Sorry about that.

Related Tutorials

Java Tutorial

Java Library

Java Tutorial

Java methods, java classes, java file handling, java how to's, java reference, java examples, java lambda expressions.

Lambda Expressions were added in Java 8.

A lambda expression is a short block of code which takes in parameters and returns a value. Lambda expressions are similar to methods, but they do not need a name and they can be implemented right in the body of a method.

The simplest lambda expression contains a single parameter and an expression:

To use more than one parameter, wrap them in parentheses:

Expressions are limited. They have to immediately return a value, and they cannot contain variables, assignments or statements such as if or for . In order to do more complex operations, a code block can be used with curly braces. If the lambda expression needs to return a value, then the code block should have a return statement.

Advertisement

Using Lambda Expressions

Lambda expressions are usually passed as parameters to a function:

Use a lambda expression in the ArrayList 's forEach() method to print every item in the list:

Try it Yourself »

Lambda expressions can be stored in variables if the variable's type is an interface which has only one method. The lambda expression should have the same number of parameters and the same return type as that method. Java has many of these kinds of interfaces built in, such as the Consumer interface (found in the java.util package) used by lists.

Use Java's Consumer interface to store a lambda expression in a variable:

To use a lambda expression in a method, the method should have a parameter with a single-method interface as its type. Calling the interface's method will run the lambda expression:

Create a method which takes a lambda expression as a parameter:

Get Certified

COLOR PICKER

colorpicker

Contact Sales

If you want to use W3Schools services as an educational institution, team or enterprise, send us an e-mail: [email protected]

Report Error

If you want to report an error, or if you want to make a suggestion, send us an e-mail: [email protected]

Top Tutorials

Top references, top examples, get certified.

HowToDoInJava

Lambda Expressions in Java

Lokesh Gupta

October 1, 2022

Lambda expressions are known to many of us who have worked on advanced languages like Scala. The term “ lambda ” has its origin in Lambda calculus that uses the Greek letter lambda (λ) to denote a function abstraction .

Lambda expressions were introduced to Java as part of Java 8 release.

1. What are Lambda Expressions?

In general programming language, a Lambda expression (or function) is an anonymous function , i.e., a function without any name or identifier, and with a list of formal parameters and a body . An arrow ( -> ) is used to separate the list of parameters and the body.

 In Java, a lambda expression is an expression that represents an instance of a functional interface .

Similar to other types in Java, lambda expressions are also typed, and their type is a functional interface type. To infer the type, the compiler looks at the left side of the assignment in a lambda expression.

Note that 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.

2. Lambda Expression Example

A typical lambda expression syntax will be like this:

For example, the below-given lambda expression takes two parameters and returns their addition. Based on the type of x and y , the expression 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.

For example, we have the following functional interface Operator . It has one method process() that takes two parameters and returns a value.

We can create lambda expressions for this functional interface in the following manner. Notice we are able to create the method implementations and immediately use them. We do not need to create a concrete class OperatorImpl that implements Operator interface.

Two good examples of functional interface types are Consumer and BiConsumer interfaces that are heavily used in Stream API for creating lambda expressions.

3. Features of Lambda Expressions

  • A lambda expression can have zero, one or more parameters .
  • The body of the lambda expressions can contain zero, one or more statements . If the body of lambda expression has a 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 then these must be enclosed in curly brackets.
  • The type of the parameters can be explicitly declared or it can be inferred from the context. In previous example, the type of addOperation and appendOperation is derived from context.
  • Multiple parameters are enclosed in mandatory parentheses and separated by commas. Empty parentheses are used to represent an empty set of parameters.
  • When there is a single parameter, if its type is inferred, it is not mandatory to use parentheses.
  • A lambda expression cannot have a  throws  clause. It is inferred from the context of its use and its body.
  • Lambda expressions cannot be generic i.e. they cannot declare type parameters.

4. More Examples

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

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

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.

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.

Example 3: Using lambda expression for adding an event listener to a GUI component

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.

5. Advantages of Lambda Expressions

Lambda expressions enable many benefits of functional programming to Java. Like most OOP languages, Java is built around classes and objects and treats only the classes as their first-class citizens. The other important programming entities, such as functions, take the back seat.

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.

Note that we were able to do everything prior to Java 8 using anonymous classes that we can do with lambda expressions, but they use a very concise syntax to achieve the same result. Let us see the comparison of the same method implementation using both techniques.

Lambda expression 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 this.

Happy Learning !!

Further reading:

  • Python Interview Questions and Answers
  • Java Concurrency Interview Questions
  • AWS Lambda Function Example
  • Amazon Alexa Custom Skill Tutorial
  • Functional Interfaces in Java
  • Java Interview Questions and Answers

guest

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.

Tutorial Series

Privacy Policy

REST API Tutorial

  • Java Tutorial
  • What is Java?
  • Installing the Java SDK
  • Your First Java App
  • Java Main Method
  • Java Project Overview, Compilation and Execution
  • Java Core Concepts
  • Java Syntax
  • Java Variables
  • Java Data Types
  • Java Math Operators and Math Class
  • Java Arrays
  • Java String
  • Java Operations
  • Java if statements
  • Java Ternary Operator
  • Java switch Statements
  • Java instanceof operator
  • Java for Loops
  • Java while Loops
  • Java Classes
  • Java Fields
  • Java Methods
  • Java Constructors
  • Java Packages
  • Java Access Modifiers
  • Java Inheritance
  • Java Nested Classes
  • Java Record
  • Java Abstract Classes
  • Java Interfaces
  • Java Interfaces vs. Abstract Classes
  • Java Annotations

Java Lambda Expressions

  • Java Modules
  • Java Scoped Assignment and Scoped Access
  • Java Exercises

Matching Lambdas to Interfaces

Interfaces with default and static methods, lambda expressions vs. anonymous interface implementations, lambda type inference, zero parameters, one parameter, multiple parameters, parameter types, var parameter types from java 11, lambda function body, returning a value from a lambda expression, lambdas as objects, local variable capture, instance variable capture, static variable capture, static method references, parameter method reference, instance method references, constructor references.

Jakob Jenkov
Last update: 2020-11-12

Java lambda expressions are new in Java 8. Java lambda expressions are Java's first step into functional programming. A Java lambda expression is thus a function which can be created without belonging to any class. A Java lambda expression can be passed around as if it was an object and executed on demand.

Java lambda expressions are commonly used to implement simple event listeners / callbacks, or in functional programming with the Java Streams API . Java Lambda Expressions are also often used in functional programming in Java .

If you prefer video, I have a video version of this tutorial in this Java Lambda Expression YouTube Playlist . Here is the first video in this playlist:

Java Lambda Expressions Tutorial

Java Lambdas and the Single Method Interface

Functional programming is very often used to implement event listeners. Event listeners in Java are often defined as Java interfaces with a single method. Here is a fictive single method interface example:

This Java interface defines a single method which is called whenever the state changes (in whatever is being observed).

In Java 7 you would have to implement this interface in order to listen for state changes. Imagine you have a class called StateOwner which can register state event listeners. Here is an example:

In Java 7 you could add an event listener using an anonymous interface implementation, like this:

First a StateOwner instance is created. Then an anonymous implementation of the StateChangeListener interface is added as listener on the StateOwner instance.

In Java 8 you can add an event listener using a Java lambda expression, like this:

The lambda expressions is this part:

The lambda expression is matched against the parameter type of the addStateListener() method's parameter. If the lambda expression matches the parameter type (in this case the StateChangeListener interface) , then the lambda expression is turned into a function that implements the same interface as that parameter.

Java lambda expressions can only be used where the type they are matched against is a single method interface. In the example above, a lambda expression is used as parameter where the parameter type was the StateChangeListener interface. This interface only has a single method. Thus, the lambda expression is matched successfully against that interface.

A single method interface is also sometimes referred to as a functional interface . Matching a Java lambda expression against a functional interface is divided into these steps:

  • Does the interface have only one abstract (unimplemented) method?
  • Does the parameters of the lambda expression match the parameters of the single method?
  • Does the return type of the lambda expression match the return type of the single method?

If the answer is yes to these three questions, then the given lambda expression is matched successfully against the interface.

From Java 8 a Java interface can contain both default methods and static methods. Both default methods and static methods have an implementation defined directly in the interface declaration. This means, that a Java lambda expression can implement interfaces with more than one method - as long as the interface only has a single unimplemented (AKA abstract) method.

In other words, an interface is still a functional interface even if it contains default and static methods, as long as the interface only contains a single unimplemented (abstract) method. Here is a video version of this little section:

Java Lambda Expressions Functional Interfaces Tutorial

The following interface can be implemented with a lambda expression:

Even though this interface contains 3 methods it can be implemented by a lambda expression, because only one of the methods is unimplemented. Here is how the implementation looks:

Even though lambda expressions are close to anonymous interface implementations, there are a few differences that are worth noting.

The major difference is, that an anonymous interface implementation can have state (member variables) whereas a lambda expression cannot. Look at this interface:

This interface can be implemented using an anonymous interface implementation, like this:

This anonymous MyEventConsumer implementation can have its own internal state. Look at this redesign:

Notice how the anonymous MyEventConsumer implementation now has a field named eventCount .

A lambda expression cannot have such fields. A lambda expression is thus said to be stateless.

Before Java 8 you would have to specify what interface to implement, when making anonymous interface implementations. Here is the anonymous interface implementation example from the beginning of this text:

With lambda expressions the type can often be inferred from the surrounding code. For instance, the interface type of the parameter can be inferred from the method declaration of the addStateListener() method (the single method on the StateChangeListener interface). This is called type inference . The compiler infers the type of a parameter by looking elsewhere for the type - in this case the method definition. Here is the example from the beginning of this text, showing that the StateChangeListener interface is not mentioned in the lambda expression:

In the lambda expression the parameter types can often be inferred too. In the example above, the compiler can infer their type from the onStateChange() method declaration. Thus, the type of the parameters oldState and newState are inferred from the method declaration of the onStateChange() method.

Lambda Parameters

Since Java lambda expressions are effectively just methods, lambda expressions can take parameters just like methods. The (oldState, newState) part of the lambda expression shown earlier specifies the parameters the lambda expression takes. These parameters have to match the parameters of the method on the single method interface. In this case, these parameters have to match the parameters of the onStateChange() method of the StateChangeListener interface:

As a minimum the number of parameters in the lambda expression and the method must match.

Second, if you have specified any parameter types in the lambda expression, these types must match too. I haven't shown you how to put types on lambda expression parameters yet (it is shown later in this text), but in many cases you don't need them.

If the method you are matching your lambda expression against takes no parameters, then you can write your lambda expression like this:

Notice how the parentheses have no content in between. That is to signal that the lambda takes no parameters.

If the method you are matching your Java lambda expression against takes one parameter, you can write the lambda expression like this:

Notice the parameter is listed inside the parentheses.

When a lambda expression takes a single parameter, you can also omit the parentheses, like this:

If the method you match your Java lambda expression against takes multiple parameters, the parameters need to be listed inside parentheses. Here is how that looks in Java code:

Only when the method takes a single parameter can the parentheses be omitted.

Specifying parameter types for a lambda expression may sometimes be necessary if the compiler cannot infer the parameter types from the functional interface method the lambda is matching. Don't worry, the compiler will tell you when that is the case. Here is a Java lambda parameter type example:

As you can see, the type ( Car ) of the car parameter is written in front of the parameter name itself, just like you would when declaring a parameter in a method elsewhere, or when making an anonymous implementation of an interface.

From Java 11 you can use the var keyword as parameter type. The var keyword was introduced in Java 10 as local variable type inference . From Java 11 var can also be used for lambda parameter types. Here is an example of using the Java var keyword as parameter types in a lambda expression:

The type of the parameter declared with the var keyword above will be inferred to the type String , because the type declaration of the variable has its generic type set to Function<String, String> , which means that the parameter type and return type of the Function is String .

The body of a lambda expression, and thus the body of the function / method it represents, is specified to the right of the -> in the lambda declaration: Here is an example:

If your lambda expression needs to consist of multiple lines, you can enclose the lambda function body inside the { } bracket which Java also requires when declaring methods elsewhere. Here is an example:

You can return values from Java lambda expressions, just like you can from a method. You just add a return statement to the lambda function body, like this:

In case all your lambda expression is doing is to calculate a return value and return it, you can specify the return value in a shorter way. Instead of this:

You can write:

The compiler then figures out that the expression a1 > a2 is the return value of the lambda expression (hence the name lambda expressions - as expressions return a value of some kind).

A Java lambda expression is essentially an object. You can assign a lambda expression to a variable and pass it around, like you do with any other object. Here is an example:

The first code block shows the interface which the lambda expression implements. The second code block shows the definition of the lambda expression, how the lambda expression is assigned to variable, and finally how the lambda expression is invoked by invoking the interface method it implements.

Variable Capture

A Java lambda expression is capable of accessing variables declared outside the lambda function body under certain circumstances. I have a video version of this section here:

Java Lambda Expressions Variable Capture Tutorial

Java lambdas can capture the following types of variables:

  • Local variables
  • Instance variables
  • Static variables

Each of these variable captures will described in the following sections.

A Java lambda can capture the value of a local variable declared outside the lambda body. To illustrate that, first look at this single method interface:

Now, look this lambda expression that implements the MyFactory interface:

Right now this lambda expression is only referencing the parameter value passed to it ( chars ). But we can change that. Here is an updated version that references a String variable declared outside the lambda function body:

As you can see, the lambda body now references the local variable myString which is declared outside the lambda body. This is possible if, and only if, the variable being references is "effectively final", meaning it does not change its value after being assigned. If the myString variable had its value changed later, the compiler would complain about the reference to it from inside the lambda body.

A lambda expression can also capture an instance variable in the object that creates the lambda. Here is an example that shows that:

Notice the reference to this.name inside the lambda body. This captures the name instance variable of the enclosing EventConsumerImpl object. It is even possible to change the value of the instance variable after its capture - and the value will be reflected inside the lambda.

The semantics of this is actually one of the areas where Java lambdas differ from anonymous implementations of interfaces. An anonymous interface implementation can have its own instance variables which are referenced via the this reference. However, an lambda cannot have its own instance variables, so this always points to the enclosing object.

Note: The above design of an event consumer is not particularly elegant. I just made it like that to be able to illustrate instance variable capture.

A Java lambda expression can also capture static variables. This is not surprising, as static variables are reachable from everywhere in a Java application, provided the static variable is accessible (packaged scoped or public).

Here is an example class that creates a lambda which references a static variable from inside the lambda body:

The value of a static variable is also allowed to change after the lambda has captured it.

Again, the above class design is a bit nonsensical. Don't think too much about that. The class primarily serves to show you that a lambda can access static variables.

Method References as Lambdas

In the case where all your lambda expression does is to call another method with the parameters passed to the lambda, the Java lambda implementation provides a shorter way to express the method call. First, here is an example single function interface:

And here is an example of creating a Java lambda instance implementing the MyPrinter interface:

Because the lambda body only consists of a single statement, we can actually omit the enclosing { } brackets. Also, since there is only one parameter for the lambda method, we can omit the enclosing ( ) brackets around the parameter. Here is how the resulting lambda declaration looks:

Since all the lambda body does is forward the string parameter to the System.out.println() method, we can replace the above lambda declaration with a method reference. Here is how a lambda method reference looks:

Notice the double colons :: . These signal to the Java compiler that this is a method reference. The method referenced is what comes after the double colons. Whatever class or object that owns the referenced method comes before the double colons.

You can reference the following types of methods:

  • Static method
  • Instance method on parameter objects
  • Instance method
  • Constructor

Each of these types of method references are covered in the following sections.

The easiest methods to reference are static methods. Here is first an example of a single function interface:

And here is a static method that we want to create a method reference to:

And finally here is a Java lambda expression referencing the static method:

Since the parameters of the Finder.find() and MyClass.doFind() methods match, it is possible to create a lambda expression that implements Finder.find() and references the MyClass.doFind() method.

You can also reference a method of one of the parameters to the lambda. Imagine a single function interface that looks like this:

The interface is intended to represent a component able to search s1 for occurrences of s2 . Here is an example of a Java lambda expression that calls String.indexOf() to search:

This is equivalent of this lambda definition:

Notice how the shortcut version references a single method. The Java compiler will attempt to match the referenced method against the first parameter type, using the second parameter type as parameter to the referenced method.

Third, it is also possible to reference an instance method from a lambda definition. First, let us look at a single method interface definition:

This interface represents a component that is capable of "deserializing" a String into an int .

Now look at this StringConverter class:

The convertToInt() method has the same signature as the deserialize() method of the Deserializer deserialize() method. Because of that, we can create an instance of StringConverter and reference its convertToInt() method from a Java lambda expression, like this:

The lambda expression created by the second of the two lines references the convertToInt method of the StringConverter instance created on the first line.

Finally it is possible to reference a constructor of a class. You do that by writing the class name followed by ::new , like this:

Too see how to use a constructor as a lambda expression, look at this interface definition:

The create() method of this interface matches the signature of one of the constructors in the String class. Therefore this constructor can be used as a lambda. Here is an example of how that looks:

This is equivalent to this Java lambda expression:

Jakob Jenkov

Java ForkJoinPool

Java SE 8: Lambda Quick Start

This tutorial introduces the new lambda expressions included in Java Platform Standard Edition 8 (Java SE 8).

Time to Complete

Approximately 1 hour

Introduction

Lambda expressions are a new and important feature included in Java SE 8. They provide a clear and concise way to represent one method interface using an expression. Lambda expressions also improve the Collection libraries making it easier to iterate through, filter, and extract data from a Collection . In addition, new concurrency features improve performance in multicore environments.

This Oracle by Example (OBE) provides an introduction to lambda expressions included in Java SE 8. An introduction to anonymous inner functions is provided, followed by a discussion of functional interfaces and the new lambda syntax. Then, examples of common usage patterns before and after lambda expressions are shown.

The next section reviews a common search use case and how Java code can be improved with the inclusion of lambda expressions. In addition, some of the common functional interfaces, Predicate and Function , provided in java.util.function are shown in action.

The OBE finishes up with a review of how the Java collection has been updated with lambda expressions.

The source code for all examples is provided to you.

Hardware and Software Requirements

The following is a list of hardware and software requirements:

  • Java Development Kit (JDK 8) early access
  • NetBeans 7.4

Prerequisites

To run the examples, you must have an early access version of JDK 8 and a copy of NetBeans 7.4 or later. Links can be found at the main Lambda site . For your convenience, here are the direct links.

  • Java Development Kit 8 (JDK8) Early Access
  • Recommended: Download the JDK 8 API Docs from the same page.
  • NetBeans 7.4 or later . Version 7.4 of NetBeans includes support for JDK 8.

Note: Builds are provided for all major operating systems. This OBE was developed using Linux Mint 13 (Ubuntu/Debian).

Install JDK8 and NetBeans following the instructions provided with the downloads. Add the bin directories for Java and NetBeans to your PATH.

Note: This OBE was last updated December 2013.

Anonymous Inner Class

In Java, anonymous inner classes provide a way to implement classes that may occur only once in an application. For example, in a standard Swing or JavaFX application a number of event handlers are required for keyboard and mouse events. Rather than writing a separate event-handling class for each event, you can write something like this.

Otherwise, a separate class that implements ActionListener is required for each event. By creating the class in place, where it is needed, the code is a little easier to read. The code is not elegant, because quite a bit of code is required just to define one method.

Functional Interfaces

The code that defines the ActionListener interface, looks something like this:

The ActionListener example is an interface with only one method. With Java SE 8, an interface that follows this pattern is known as a "functional interface."

Note: This type of interface , was previously known as a Single Abstract Method type (SAM).

Using functional interfaces with anonymous inner classes are a common pattern in Java. In addition to the EventListener classes, interfaces like Runnable and Comparator are used in a similar manner. Therefore, functional interfaces are leveraged for use with lambda expressions.

Lambda Expression Syntax

Lambda expressions address the bulkiness of anonymous inner classes by converting five lines of code into a single statement. This simple horizontal solution solves the "vertical problem" presented by inner classes.

A lambda expression is composed of three parts.

Argument List Arrow Token Body

The body can be either a single expression or a statement block. In the expression form, the body is simply evaluated and returned. In the block form, the body is evaluated like a method body and a return statement returns control to the caller of the anonymous method. The break and continue keywords are illegal at the top level, but are permitted within loops. If the body produces a result, every control path must return something or throw an exception.

Take a look at these examples:

The first expression takes two integer arguments, named x and y , and uses the expression form to return x+y . The second expression takes no arguments and uses the expression form to return an integer 42. The third expression takes a string and uses the block form to print the string to the console, and returns nothing.

With the basics of syntax covered, let's look at some examples.

Lambda Examples

Here are some common use cases using the previously covered examples.

Runnable Lambda

Here is how you write a Runnable using lambdas.

In both cases, notice that no parameter is passed and is returned. The Runnable lambda expression, which uses the block format, converts five lines of code into one statement.

Comparator Lambda

In Java, the Comparator class is used for sorting collections. In the following example, an ArrayList consisting of Person objects is sorted based on surName . The following are the fields included in the Person class.

The following code applies a Comparator by using an anonymous inner class and a couple lambda expressions.

Lines 17 - 21 are easily replaced by the lambda expression on line 32. Notice that the first lambda expression declares the parameter type passed to the expression. However, as you can see from the second expression, this is optional. Lambda supports "target typing" which infers the object type from the context in which it is used. Because we are assigning the result to a Comparator defined with a generic, the compiler can infer that the two parameters are of the Person type.

Listener Lambda

Finally, let's revisit the ActionListener example.

Notice that the lambda expression is passed as a parameter. Target typing is used in a number of contexts including the following:

  • Variable declarations
  • Assignments
  • Return statements
  • Array initializers
  • Method or constructor arguments
  • Lambda expression bodies
  • Conditional expressions ?:
  • Cast expressions

A NetBeans project containing the source files for the examples covered to this point is in the following zip file.

LambdaExamples01.zip

Improving Code with Lambda Expressions

This section builds upon the previous examples to show you how lambda expressions can improve your code. Lambdas should provide a means to better support the Don't Repeat Yourself (DRY) principle and make your code simpler and more readable.

A Common Query Use Case

A common use case for programs is to search through a collection of data to find items that match a specific criteria. In the excellent "Jump-Starting Lambda" presentation at JavaOne 2012, Stuart Marks and Mike Duigou walk though just such a use case. Given a list of people, various criteria are used to make robo calls (automated phone calls) to matching persons. This tutorial follows that basic premise with slight variations.

In this example, our message needs to get out to three different groups in the United States:

  • Drivers: Persons over the age of 16
  • Draftees: Male persons between the ages of 18 and 25
  • Pilots (specifically commercial pilots): Persons between the ages of 23 and 65

The actual robot that does all this work has not yet arrived at our place of business. Instead of calling, mailing or emailing, a message is printed to the console. The message contains a person's name, age, and information specific to the target medium (for example, email address when emailing or phone number when calling).

Person Class

Each person in the test list is defined by using the Person class with the following properties:

The Person class uses a Builder to create new objects. A sample list of people is created with the createShortList method. Here is a short code fragment of that method. Note: All source code for this tutorial is included in a NetBeans project that is linked at the end of this section.

A First Attempt

With a Person class and search criteria defined, you can write a RoboContact class. One possible solution defines a method for each use case:

RoboContactsMethods.java

As you can see from the names ( callDrivers , emailDraftees , and mailPilots ) the methods describe the kind of behavior that is taking place. The search criteria is clearly conveyed and an appropriate call is made to each robo action. However, this design has some negatives aspects:

  • The DRY principle is not followed.
  • Each method repeats a looping mechanism.
  • The selection criteria must be rewritten for each method
  • A large number of methods are required to implement each use case.
  • The code is inflexible. If the search criteria changed, it would require a number of code changes for an update. Thus, the code is not very maintainable.

Refactor the Methods

How can the class be fixed? The search criteria is a good place to start. If test conditions are isolated in separate methods, that would be an improvement.

RoboContactMethods2.java

The search criteria are encapsulated in a method, an improvement over the previous example. The test conditions can be reused and changes flow back throughout the class. However there is still a lot of repeated code and a separate method is still required for each use case. Is there a better way to pass the search criteria to the methods?

Anonymous Classes

Before lambda expressions, anonymous inner classes were an option. For example, an interface ( MyTest.java ) written with one test method that returns a boolean (a functional interface) is a possible solution. The search criteria could be passed when the method is called. The interface looks like this:

The updated robot class looks like this:

RoboContactsAnon.java

That is definitely another improvement, because only three methods are needed to perform robotic operations. However, there is a slight problem with ugliness when the methods are called. Check out the test class used for this class:

RoboCallTest03.java

This is a great example of the "vertical" problem in practice. This code is a little difficult to read. In addition, we have to write custom search criteria for each use case.

Lambda Expressions Get it Just Right

Lambda expressions solve all the problems encountered so far. But first a little housekeeping.

java.util.function

In the previous example, the MyTest functional interface passed anonymous classes to methods. However, writing that interface was not necessary. Java SE 8 provides the java.util.function package with a number of standard functional interfaces. In this case, the Predicate interface meets our needs.

The test method takes a generic class and returns a boolean result. This is just what is needed to make selections. Here is the final version of the robot class.

RoboContactsLambda.java

With this approach only three methods are needed, one for each contact method. The lambda expression passed to the method selects the Person instances that meet the test conditions.

Vertical Problem Solved

Lambda expressions solve the vertical problem and allow the easy reuse of any expression. Take a look at the new test class updated for lambda expressions.

RoboCallTest04.java

Notice that a Predicate is set up for each group: allDrivers , allDraftees , and allPilots . You can pass any of these Predicate interfaces to the contact methods. The code is compact and easy to read, and it is not repetitive.

The NetBeans project with the source code is included in the following zip file.

RoboCallExample.zip

The java.util.function Package

Of course, Predicate is not the only functional interface provided with Java SE 8. A number of standard interfaces are designed as a starter set for developers.

  • Predicate : A property of the object passed as argument
  • Consumer : An action to be performed with the object passed as argument
  • Function : Transform a T to a U
  • Supplier : Provide an instance of a T (such as a factory)
  • UnaryOperator : A unary operator from T -> T
  • BinaryOperator : A binary operator from (T, T) -> T

In addition, many of these interfaces also have primitive versions. This should give you a great starting point for your lambda expressions.

Eastern Style Names and Method References

When working on the previous example, I decided it would be nice to have a flexible printing system for the Person class. One feature requirement is to display names in both a western style and an eastern style. In the West, names are displayed with the given name first and the surname second. In many eastern cultures, names are displayed with the surname first and the given name second.

An Old Style Example

Here is an example of how to implement a Person printing class without lambda support.

Person.java

A method exists for each style that prints out a person.

The Function Interface

The Function interface is useful for this problem. It has only one method apply with the following signature:

public R apply(T t){ }

It takes a generic class T and returns a generic class R . For this example, pass the Person class and return a String . A more flexible print method for person could be written like this:

That is quite a bit simpler. A Function is passed to the method and a string returned. The apply method processes a lambda expression which determines what Person information is returned.

How are the Function s defined? Here is the test code that calls the previous method.

NameTestNew.java

The first loop just prints given name and the email address. But any valid expression could be passed to the printCustom method. Eastern and western print styles are defined with lambda expressions and stored in a variable. The variables are then passed to the final two loops. The lambda expressions could very easily be incorporated into a Map to make their reuse much easier. The lambda expression provides a great deal of flexibility.

Sample Output

Here is some sample output from the program.

The NetBeans project with the source code for the examples in this section is included in the following zip file.

LambdaFunctionExamples.zip

Lambda Expressions and Collections

The previous section introduced the Function interface and finished up examples of basic lambda expression syntax. This section reviews how lambda expressions improve the Collection classes.

In the examples created so far, the collections classes were used quite a bit. However, a number of new lambda expression features change the way collections are used. This section introduces a few of these new features.

Class Additions

The drivers, pilots, and draftees search criteria have been encapsulated in the SearchCriteria class.

SearchCriteria.java

The Predicate based search criteria are stored in this class and available for our test methods.

The first feature to look at is the new forEach method available to any collection class. Here are a couple of examples that print out a Person list.

Test01ForEach.java

The first example shows a standard lambda expression which calls the printWesternName method to print out each person in the list. The second example demonstrates a method reference . In a case where a method already exists to perform an operation on the class, this syntax can be used instead of the normal lambda expression syntax. Finally, the last example shows how the printCustom method can also be used in this situation. Notice the slight variation in variable names when one lambda expression is included in another.

You can iterate through any collection this way. The basic structure is similar to the enhanced for loop. However, including an iteration mechanism within the class provides a number of benefits.

Chaining and Filters

In addition to looping through the contents of a collection, you can chain methods together. The first method to look at is filter which takes a Predicate interface as a parameter.

The following example loops though a List after first filtering the results.

Test02Filter.java

The first and last loops demonstrate how the List is filtered based on the search criteria. The output from the last loop looks like following:

Getting Lazy

These features are useful, but why add them to the collections classes when there is already a perfectly good for loop? By moving iteration features into a library, it allows the developers of Java to do more code optimizations. To explain further, a couple of terms need definitions.

  • Laziness: In programming, laziness refers to processing only the objects that you want to process when you need to process them. In the previous example, the last loop is "lazy" because it loops only through the two Person objects left after the List is filtered. The code should be more efficient because the final processing step occurs only on the selected objects.
  • Eagerness: Code that performs operations on every object in a list is considered "eager". For example, an enhanced for loop that iterates through an entire list to process two objects, is considered a more "eager" approach.

By making looping part of the collections library, code can be better optimized for "lazy" operations when the opportunity arises. When a more eager approach makes sense (for example, computing a sum or an average), eager operations are still applied. This approach is a much more efficient and flexible than always using eager operations.

The stream Method

In the previous code example, notice that the stream method is called before filtering and looping begin. This method takes a Collection as input and returns a java.util.stream.Stream interface as the output. A Stream represents a sequence of elements on which various methods can be chained. By default, once elements are consumed they are no longer available from the stream. Therefore, a chain of operations can occur only once on a particular Stream . In addition, a Stream can be serial(default) or parallel depending on the method called. An example of a parallel stream is included at the end of this section.

Mutation and Results

As previously mentioned, a Stream is disposed of after its use. Therefore, the elements in a collection cannot be changed or mutated with a Stream . However, what if you want to keep elements returned from your chained operations? You can save them to a new collection. The following code shows how to do just that.

Test03toList.java

The collect method is called with one parameter, the Collectors class. The Collectors class is able to return a List or Set based on the results of the stream. The example shows how the result of the stream is assigned to a new List which is iterated over.

Calculating with map

The map method is commonly used with filter . The method takes a property from a class and does something with it. The following example demonstrates this by performing calculations based on age.

Test04Map.java

And the output from the class is:

The program calculates the average age of pilots in our list. The first loop demonstrates the old style of calculating the number by using a for loop. The second loop uses the map method to get the age of each person in a serial stream. Notice that totalAge is a long . The map method returns an IntSteam object, which contains a sum method that returns a long .

Note: To compute the average the second time, calculating the sum of ages is unnecessary. However, it is instructive to show an example with the sum method.

The last loop computes the average age from the stream. Notice that the parallelStream method is used to get a parallel stream so that the values can be computed concurrently. The return type is a bit different here as well.

The NetBeans project with source code for the examples is in the following zip file.

LambdaCollectionExamples.zip

In this tutorial, you learned how to use:

  • Anonymous inner classes in Java.
  • Lambda expressions to replace anonymous inner classes in Java SE 8.
  • The correct syntax for lambda expressions.
  • A Predicate interface to perform searches on a list.
  • A Function interface to process an object and produce a different type of object.
  • New features added to Collections in Java SE 8 that support lambda expressions.

For further information on Java SE 8 and lambda expressions, see the following:

  • Project Lambda
  • State of the Lambda
  • State of the Lambda Collections
  • Jump-Starting Lambda JavaOne 2012 (You Tube)
  • To learn more about Java and related topics check out the Oracle Learning Library .
  • Lead Curriculum Developer: Michael Williams
  • QA: Juan Quesada Nunez

To navigate this Oracle by Example tutorial, note the following:

To navigate to a particular section in this tutorial, select the topic from the list.

Unraveling Java Lambda Expressions: A Deep Dive

Lambda expressions, introduced in Java 8, brought a whole new paradigm to the language, paving the way for functional programming constructs within the predominantly object-oriented environment. This blog post will delve into the intricacies of lambda expressions, discussing their syntax, usage, benefits, and the conditions under which you would choose to use them.

Understanding Java Lambda Expressions

Lambda expressions, also known as anonymous functions, are a way to represent instances of functional interfaces—an interface with only one abstract method. Lambda expressions offer a concise syntax to create anonymous methods, removing the need to create anonymous inner classes for implementing functional interfaces.

The syntax of a lambda expression is as follows:

  • parameter is the input parameter for the lambda function. It can be zero, one, or more parameters.
  • -> is the lambda arrow which separates the parameters and the body of the lambda expression.
  • {body} is the function body which contains the expressions and statements of the lambda function.

Here's a simple example of a lambda expression:

The Power of Lambda Expressions

The introduction of lambda expressions brought about several advantages:

Conciseness: Lambda expressions are much more concise than anonymous inner classes. The verbosity of the latter, especially when implementing functional interfaces, can be greatly reduced with lambda expressions.

Functional Programming: Lambda expressions ushered Java into the world of functional programming, making it easier to perform operations like map, filter, and reduce on collections.

Ease of Use with Streams: Lambda expressions work seamlessly with the Stream API introduced in Java 8, enabling operations on sequences of elements, such as bulk operations on collections like filtering and aggregating data.

Parallel Execution: The introduction of lambda expressions and the Stream API has made parallel execution more accessible and easier to implement in Java.

Lambda Expressions in Action

Now let's look at some practical examples to understand the usage of lambda expressions in Java.

Suppose we have a List of String and we want to print each element of the list. We can do this using lambda expressions as follows:

Now, let's assume we have a List of Integer , and we want to find the sum of all even numbers in the list. We can use lambda expressions with the Stream API to achieve this:

Lambda Expressions and Functional Interfaces

Lambda expressions in Java are heavily tied with Functional Interfaces. A Functional Interface is an interface with only one abstract method, excluding default and static methods. Java 8 comes with several predefined functional interfaces under the java.util.function package. Examples include Predicate<T> , Function<T,R> , and Supplier<T> . Lambda expressions offer a quick and convenient way to implement these interfaces.

For example, let's use the Predicate<T> functional interface which has an abstract method boolean test(T t) :

Type Inference in Lambda Expressions

Java’s lambda expressions include type inference. This means you don't have to explicitly mention the type of the parameters in a lambda expression. The Java compiler is capable of inferring the type of the parameters from the context in which the lambda is used.

For example, you could write the previous lambda expression as:

Variable Capture in Lambda Expressions

Lambda expressions in Java have the capability of accessing variables from their enclosing scopes, including instance variables, static variables, and local variables.

Lambda Expressions and Method References

Method references are a simplified form of lambda expressions which can be used when your lambda expression is simply calling an existing method. They use the :: symbol.

Lambda Expressions and Exception Handling

Lambda expressions and exceptions can be a bit tricky. The key rule here is that a lambda expression can throw an exception if the abstract method in the functional interface throws it.

Let's take the Function<T,R> interface. Its apply(T t) method does not throw any checked exceptions. Therefore, if you're using this interface with a lambda and the lambda's body can throw a checked exception, you'll have to handle the exception within the lambda:

Performance Considerations

While lambda expressions can make your code more readable and concise, it's also important to note that improper use of lambdas and streams can sometimes lead to inefficient code. Always consider the trade-off between readability and performance in your specific use case.

For example, using a parallel stream when the number of elements is small can actually degrade performance due to the overhead of setting up the parallelism. Similarly, excessive use of boxed operations or unnecessary intermediate operations in a stream can lead to increased memory consumption.

In conclusion, while lambda expressions are a powerful tool in Java, they should be used appropriately and judiciously. They can greatly improve the conciseness and readability of your code when used correctly, but like any tool, they have their proper place and should not be overused.

Lambda Expressions and Collections Sorting

Lambda expressions can be used with the Collections.sort() method to sort collections based on various conditions.

For example, if you have a list of Person objects and you want to sort them by their age property, you could use a lambda expression as follows:

Lambda Expressions in Event Handling

In graphical user interface (GUI) applications, lambda expressions can be used to handle events. For instance, with JavaFX or Swing, you could use a lambda expression to handle a button click event:

Lambda Expressions in Threads

Lambda expressions can be used to create threads. For example, instead of creating an anonymous Runnable object, you can use a lambda expression:

Lambda Expressions with Optional

Java 8 introduced the Optional class, which is a container that may or may not contain a non-null value. Lambda expressions can be used with the Optional.ifPresent() method to execute some code if the Optional contains a value:

Lambda Expressions with Map

With Java 8, new methods were added to the Map interface that work well with lambda expressions. For example, you could use the Map.forEach() method to iterate over the map:

Lambda Expressions with Comparator

Lambda expressions can be used with the Comparator interface, which is a functional interface, to compare objects in a more flexible way. For instance, to compare strings by their lengths:

In summary, lambda expressions represent a significant enhancement to the Java programming language, allowing developers to write more concise and efficient code. By enabling functional programming constructs and seamless integration with the Stream API, lambda expressions have become an indispensable tool in the Java developer's toolkit.

Remember, as with any programming construct, lambda expressions should be used judiciously and where appropriate. The aim should always be to write clear, maintainable, and efficient code.

Guide to Functional Interfaces and Lambda Expressions in Java

java lambda assignment

  • Introduction

Java is an object-oriented language, imperative in its essence (contrasting with the declarative practice that is functional programming). Nonetheless, it was possible to apply functional principles to Java programs prior to version 8, however it required additional work to bypass the innate structure of the language and resulted in convoluted code. Java 8 brought about ways to harness the true efficacy and ease to which functional programming aspires.

This guide aims to provide a holistic view into functional programming, a concept that appears rather esoteric to the developer of OOP background. Because of this, material is oftentimes scattered and scarce. We will first establish an understanding of the core concepts of functional programming and the ways in which Java implements them.

Because there's a lot of misunderstanding regarding Functional Programming for those with an OOP background - we'll start out with a primer on Functional Programming and its benefits.

Then, we'll dive into Lambda Expressions as Java's implementation of first-class functions , as well as functional interfaces , followed by a quick look at Java's function package.

  • Primer on Functional Programming

Functional programming is a programming paradigm that revolves around - well, functions . Although object-oriented programming also employs functions, the building blocks of the program are the objects. Objects are used to mediate the state and behavior patterns inside the program, while functions are there to take care of the control flow.

Functional programming separates behavior from objects.

Functions then have the liberty to act as first-class entities. They can be stored in variables and can be arguments or the return values of other functions without needing to be accompanied by an object. These discrete entities are termed first-class functions , while the functions enclosing them are named higher-order functions .

Functional programming also has a different approach towards the program state. In OOP, the desired outcome of an algorithm is achieved by manipulating the state of the program. Functional practice refrains from causing state changes altogether. The functions are generally pure , meaning that they do not cause any side effects; they don't alter global variables, perform IO or throw exceptions.

There exist purely functional languages, some of which enforce the use of immutable variables. There also exist purely object-oriented languages. Java is a multi paradigm language; it has the ability to teeter between different programming styles and utilize the benefits of multiple paradigms in the same code-base.

  • The Benefits of Functional Programming

Functional programming, among all else, offers flexibility. We can create layers of generalization. We can scaffold behavioral patterns and customize them by passing in additional instructions when needed.

Object-oriented programming also has ways to create these patterns, though they depend on the use of objects. Interfaces, for example, can be used to create a scaffold, and each class implementing the interface can tailor the behavior defined in its own way. Then again, an object should always be there to carry the variants. Functional programming provides a more elegant way.

Furthermore, functional programming uses pure functions. Since pure functions can not alter states outside of their scope, they do not have the power to affect one another; each function is fully independent . This gives programmers the ability to dispose of the functions when they are no longer needed, alter the execution order at will, or execute functions in parallel.

Since pure functions are not dependent on external values, re-executing the code with the same arguments will result in the same outcome every time. This supports the optimization technique called memoization (not "memorization"), the process of caching the results of an expensive execution sequence to retrieve them when needed elsewhere in the program.

Additionally, the ability to treat functions as first-class entities allows for currying - the technique of subdividing the execution sequence of a function to perform at separate times. A function with multiple parameters can be partially executed at the point where one parameter is supplied, and the rest of the operation can be stored and delayed until the next parameter is given.

  • Lambda Expressions in Java
  • Functional Interfaces and Lambda Expressions

Java implements the basic block of functional programming, the pure first-class functions , in the form of lambda expressions .

Lambda expressions are the couriers via which Java moves around a set of behavior.

Lambda expressions, by and large, have the structure of:

Then again, this structure is subject to change. Let's see the lambdas in action first and elaborate on the adapted versions of their syntax later on. We'll start off by defining a functional interface :

A functional interface is an interface that has exactly one abstract method.

We can then implement this interface's method, through a lambda expression:

With this implementation, the concat() method now has a body and can be used later on:

Let's take a step back and peel away at what we just did. The StringConcat interface holds a single abstract method ( concat() ) which takes two string parameters and is expected to return a string value.

StringConcat is an interface and can not be instantiated. On the right-hand side of the assignment, the compiler expects to find an instantiation of a class that implements StringConcat , not a function. Yet, the code works seamlessly.

Java is inherently object-oriented. Everything is an object in Java (more accurately, everything extends into an Object class), including lambda expressions.

Even though we get to treat lambdas as first-class functions, Java interprets them as objects. Intrinsic in that, the lambda expression assigned to be of type StringConcat is essentially an implementing class and therefore has to define the behavior for StringConcat 's method .

The concat() method can be called in the same way object methods are called ( lambdaConcat.concat() ), and it behaves as defined by the lambda expression:

At the end of the program execution, console should read:

  • Lambdas as Arguments

Lambdas shine more when they're passed in as arguments to methods, instead of used as utility classes. Let's implement a function that filters through a list of people to find a set statistically likely to be "likable" by some set standard.

Note: Our standard for "friendliness" will be set just for illustrational purposes, and doesn't reflect any real research or statistical analysis.

The function will accept a mass and bias to filter out the mass ending up with a group of people that are, according to the opinion applied, "nice people":

The bias in the parameter list will be a function - a lambda expression - that the higher-order function refers to decide the appeal of each person in the mass.

Let's start by creating a Person class to represent a person:

The Person class is assigned various fields to outline each of their characters. Each Person has a name, age, a sociability signifier, a pet preference selected among a set of constants, and a list of hobbies.

With a Person class, let's go ahead, defining a Bias functional interface with a test() function. The test() function will, naturally, be abstract and without implementation by default:

Once we implement it, the test() function will test a person for their likability, according to some set of biases. Let's go ahead and define the filter() function as well, which accepts a list of people and a Bias for filtering:

Based on the result of the test() function, we either add or skip adding a person to the filteredPeople list, which is, well, how filters work. Keep in mind that the actual implementation of the test() function still doesn't exist, and will only gain body after we define its body as a lambda function.

Since the filter() method accepts the Bias functional interface, we can anonymously create the lambda function in the filter() call:

Finally, this is where it all comes together - we've defined the body of the functional interface via a lambda expression:

The lambda expression gets evaluated and compared against the signature of Bias 's test() method and this body is then used as the test() method's check, and returns a true or false based on the value of the isExtrovert() method.

Keep in mind that we could've used anybody here, since Bias is a "plug-and-play" functional interface.

The ability to create a method that can adjust its approach in this manner is a delicacy of functional programming.

The filter() method is a higher-degree function that takes another function as its parameter according to which it alters its behavior, where the other function is fully fluid.

There exist myriad ways in which we can select a Person to hang out with. Putting the ethics of filtering like this to the side, we may choose to hang out with people of a certain age scope, prefer extroverts, or we may be desperate to find someone who would go to the gym with us yet be disinclined to share their cat stories.

Various selection criteria can be chained together as well.

Of course, it is possible to create different methods to serve each scenario - yet does it make sense to purchase different drills to use on different materials when you can simply change the drill bits?

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

The filter() method provides flexibility. It defines the main behavior, selecting . Later on, in the program, we can use this method for any selection and just pass in " how to" .

It's worth noting that the filter() method starts by creating a new ArrayList , as functional practice refrains from changing the state of the program. Instead of operating on and manipulating the original list, we start with an empty list which we later populate with desired Person s.

The list holding only the extroverts is then passed to list() to be displayed in the console:

This example showcases the flexibility and liquidity of functional interfaces and their lambda-created bodies.

  • Lambdas and Interfaces

So far, the lambda expressions were ascribed to an interface. This will be the norm any time we want to implement first-class functions in Java.

Consider the implementation of arrays. When an array's elements are needed somewhere in the code, we call the array by its assigned name and access its elements through that name instead of moving the actual set of data around. And since we have declared it to be an array of one type, every time we want to operate on it, the compiler knows that the variable name is referring to an array and that this array stores objects of a significant type. The compiler thus can decide the capabilities of this variable and the actions it can perform.

Java is a statically-typed language - it requires this knowledge for every variable.

Every variable must state its name and its type before it can be used (this is called declaring a variable). Lambda expressions are not an exception to this rule.

When we want to use lambda expressions, we need to let the compiler know the nature of the encapsulated behavior. The interfaces we bind to lambda expressions are there to provide this information; they act as footnotes the compiler can refer to.

We could carry the name and type information along with the lambda expression itself. However, more often than not, we will use the same type of lambdas to create a variety of particular behaviors.

It's good practice to avoid redundancy in the code; typing the same information many times over will only make our code error-prone and our fingers weary.

  • Lambda Expression Syntax

Lambdas come in many flavors. While the lambda operator ( -> ) is set firm, brackets and type declarations can be removed in some circumstances.

Lambda takes its simplest form when there only exists one parameter and one operation to perform inside the function body.

We no longer need parentheses around the parameter, no type declaration needed, no curly brackets enclosing the statement, and no requirement to use the return keyword.

The lambda expression can take more than one parameter or may not take any. In those cases, we are bound to include parentheses:

If the function body includes more than one statement, the curly braces and, if the return type is not void, the return keyword are also required:

The type declaration for the parameters can be omitted fully. Though if one parameter amongst many has its type declared, others are required to follow in its footsteps:

Both statements above are valid. However, the compiler would complain if the program were to use the expression below:

  • Functional Interfaces
  • @FunctionalInterface

Any interface with a single abstract method qualifies to be a functional interface; there is no additional requirement. Yet, a distinction may be necessary for large codebases.

Let's take the Bias interface from Lambdas as Arguments , and add another abstract method to it:

The Bias interface was connected to a lambda expression, yet the compiler does not complain if we add another method to the interface, which turns it from a functional interface to a regular one.

The compiler has no way of knowing that Bias was supposed to be a functional interface until it encounters the lambda expression bound to it. Since a regular interface can have many abstract methods (and since there is no indication that this interface is not like any other), the compiler will blame the lambda expression for it tries to bind to a non-functional interface.

To avoid this, Java provides a way to mark the interfaces that serve lambda expressions, explicitly:

The @FunctionalInterface annotation will let the compiler know that this interface is meant to be functional, and therefore any additional abstract method is not welcome here.

The compiler can now interfere on the spot when someone makes the mistake of adding another method to this interface, though the chances of that are lowered yet again by the @FunctionalInterface mark.

  • Default and Static Methods

Up until Java 8, interfaces were limited to having abstract methods and constants. Along with functional programming support came the addition of default and static methods to interface definitions.

An abstract method defines a skeleton for the method to be implemented. A default method, on the other hand, is no mere skeleton; it is explicitly defined. Yet, an implementing class is given the option to override the default methods. If they don't, the default implementation kicks in:

Let's implement this interface without implementing the bark() method:

Now, let's instantiate it and take a look at the default implementation kicking in:

A static method of an interface, on the other hand, is the private property of that interface. It can only be called via the interface name and cannot be overridden by the implementing classes:

Let's implement the interface:

And instantiate a GermanSheperd :

This results in:

  • The java.util.function Package

The extent of information functional interfaces provide is limited. The method definitions can easily be generalized to cover common use cases, and they can be fairly flexible in their implementations.

The return type of the abstract method can be any of the primitive types (integer, string, double, etc.) or can be void. Any classes that are defined inside the program can also be declared as the return type, though the generic type would cover all.

The same logic applies to the parameter types. Even though the number of parameters to a method can still vary, there exists a logical limit for the sake of code quality. The list of names that can be assigned to a function is also limitless, though it rarely matters.

In the end, we are left with a handful of permutations that can cover most of the common use cases.

Java employs 43 predefined functional interfaces, in the java.util.function package, to serve these scenarios. We can group them in five groups:

In their individual guides - we'll be covering each of these groups separately.

In this guide, we've taken a holistic look at Functional Programming in Java and its implementation. We've covered Functional Interfaces, as well as Lambda Expressions as the building blocks for functional code.

You might also like...

  • Java: Finding Duplicate Elements in a Stream
  • Spring Boot with Redis: HashOperations CRUD Functionality
  • Spring Cloud: Hystrix
  • Java Regular Expressions - How to Validate Emails

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

In this article

Make clarity from data - quickly learn data visualization with python.

Learn the landscape of Data Visualization tools in Python - work with Seaborn , Plotly , and Bokeh , and excel in Matplotlib !

From simple plot types to ridge plots, surface plots and spectrograms - understand your data and learn to draw conclusions from it.

© 2013- 2024 Stack Abuse. All rights reserved.

# Lambda Expressions

Lambda expressions provide a clear and concise way of implementing a single-method interface using an expression. They allow you to reduce the amount of code you have to create and maintain. While similar to anonymous classes, they have no type information by themselves. Type inference needs to happen.

Method references implement functional interfaces using existing methods rather than expressions. They belong to the lambda family as well.

# Introduction to Java lambdas

# functional interfaces.

(opens new window) or static methods. (For this reason, they are sometimes referred to as Single Abstract Method Interfaces, or SAM Interfaces).

(opens new window) annotation can be added. This has no special effect, but a compiler error will be generated if this annotation is applied to an interface which is not functional, thus acting as a reminder that the interface should not be changed.

Conversely, this is not a functional interface, as it has more than one abstract method:

This is also not a functional interface, as it does not have any methods:

Take note of the following. Suppose you have

interface Parent { public int parentMethod(); }

interface Child extends Parent { public int ChildMethod(); }

Then Child cannot be a functional interface since it has two specified methods.

(opens new window) . For example, the built-in interface Predicate<T> wraps a single method which inputs a value of type T and returns a boolean .

The basic structure of a Lambda expression is:

(opens new window)

fi will then hold a singleton instance of a class, similar to an anonymous class, which implements FunctionalInterface and where the one method's definition is { System.out.println("Hello"); } . In other words, the above is mostly equivalent to:

The lambda is only "mostly equivalent" to the anonymous class because in a lambda, the meaning of expressions like this , super or toString() reference the class within which the assignment takes place, not the newly created object.

You cannot specify the name of the method when using a lambda—but you shouldn't need to, because a functional interface must have only one abstract method, so Java overrides that one.

In cases where the type of the lambda is not certain, (e.g. overloaded methods) you can add a cast to the lambda to tell the compiler what its type should be, like so:

If the functional interface's single method takes parameters, the local formal names of these should appear between the brackets of the lambda. There is no need to declare the type of the parameter or return as these are taken from the interface (although it is not an error to declare the parameter types if you want to). Thus, these two examples are equivalent:

The parentheses around the argument can be omitted if the function only has one argument:

# Implicit Returns

If the code placed inside a lambda is a Java expression rather than a statement , it is treated as a method which returns the value of the expression. Thus, the following two are equivalent:

# Accessing Local Variables (value closures)

Since lambdas are syntactic shorthand for anonymous classes, they follow the same rules for accessing local variables in the enclosing scope; the variables must be treated as final and not modified inside the lambda.

# Accepting Lambdas

Because a lambda is an implementation of an interface, nothing special needs to be done to make a method accept a lambda: any function which takes a functional interface can also accept a lambda.

# The Type of a Lambda Expression

A lambda expression, by itself, does not have a specific type. While it is true that the types and number of parameters, along with the type of a return value can convey some type information, such information will only constrain what types it can be assigned to. The lambda receives a type when it is assigned to a functional interface type in one of the following ways:

  • Direct assignment to a functional type, e.g. myPredicate = s -> s.isEmpty()
  • Passing it as a parameter that has a functional type, e.g. stream.filter(s -> s.isEmpty())
  • Returning it from a function that returns a functional type, e.g. return s -> s.isEmpty()
  • Casting it to a functional type, e.g. (Predicate<String>) s -> s.isEmpty()

Until any such assignment to a functional type is made, the lambda does not have a definite type. To illustrate, consider the lambda expression o -> o.isEmpty() . The same lambda expression can be assigned to many different functional types:

Now that they are assigned, the examples shown are of completely different types even though the lambda expressions looked the same, and they cannot be assigned to each other.

# Using Lambda Expressions to Sort a Collection

# sorting lists.

(opens new window) interface with an anonymous (or named) class when sorting a list 1 :

Starting with Java 8, the anonymous class can be replaced with a lambda expression. Note that the types for the parameters p1 and p2 can be left out, as the compiler will infer them automatically:

(opens new window) expressed using the :: (double colon) symbol.

A static import allows us to express this more concisely, but it is debatable whether this improves overall readability:

Comparators built this way can also be chained together. For example, after comparing people by their first name, if there are people with the same first name, the thenComparing method with also compare by last name:

1 - Note that Collections.sort(...) only works on collections that are subtypes of List . The Set and Collection APIs do not imply any ordering of the elements.

# Sorting maps

You can sort the entries of a HashMap by value in a similar fashion. (Note that a LinkedHashMap must be used as the target. The keys in an ordinary HashMap are unordered.)

# Method References

Method references allow predefined static or instance methods that adhere to a compatible functional interface to be passed as arguments instead of an anonymous lambda expression.

Assume that we have a model:

# Instance method reference (to an arbitrary instance)

The equivalent lambda:

In this example, a method reference to the instance method getName() of type Person , is being passed. Since it's known to be of the collection type, the method on the instance (known later) will be invoked.

# Instance method reference (to a specific instance)

Since System.out is an instance of PrintStream , a method reference to this specific instance is being passed as an argument.

# Static method reference

Also for transforming streams we can apply references to static methods:

This example passes a reference to the static valueOf() method on the String type. Therefore, the instance object in the collection is passed as an argument to valueOf() .

# Reference to a constructor

(opens new window) to see how to collect elements to collection.

The single String argument constructor of the Integer type is being used here, to construct an integer given the string provided as the argument. In this case, as long as the string represents a number, the stream will be mapped to Integers. The equivalent lambda:

# Cheat-Sheet

Method Reference Format Code Equivalent Lambda
Static method
Non-static method (on instance )
Non-static method (no instance)
Constructor
Array constructor

* instance can be any expression that evaluates to a reference to an instance, e.g. getInstance()::method , this::method

** If TypeName is a non-static inner class, constructor reference is only valid within the scope of an outer class instance

# Implementing multiple interfaces

(opens new window) ) since they don't add abstract methods.

(opens new window) with a custom Comparator and then serialize it and send it over the network. The trivial approach:

doesn't work since the lambda for the comparator does not implement Serializable . You can fix this by using intersection types and explicitly specifying that this lambda needs to be serializable:

(opens new window) where almost everything has to be serializable), you can create empty interfaces and use them in your code instead:

This way you're guaranteed that the passed comparator will be serializable.

# Lambda - Listener Example

Anonymous class listener

Before Java 8, it’s very common that an anonymous class is used to handle click event of a JButton, as shown in the following code. This example shows how to implement an anonymous listener within the scope of btn.addActionListener .

Lambda listener

Because the ActionListener interface defines only one method actionPerformed() , it is a functional interface which means there’s a place to use Lambda expressions to replace the boilerplate code. The above example can be re-written using Lambda expressions as follows:

# Java Closures with lambda expressions.

A lambda closure is created when a lambda expression references the variables of an enclosing scope (global or local). The rules for doing this are the same as those for inline methods and anonymous classes.

Local variables from an enclosing scope that are used within a lambda have to be final . With Java 8 (the earliest version that supports lambdas), they don't need to be declared final in the outside context, but must be treated that way. For example:

This is legal as long as the value of the n variable is not changed. If you try to change the variable, inside or outside the lambda, you will get the following compilation error:

"local variables referenced from a lambda expression must be final or effectively final ".

For example:

If it is necessary to use a changing variable within a lambda, the normal approach is to declare a final copy of the variable and use the copy. For example

Naturally, the body of the lambda does not see the changes to the original variable.

Note that Java does not support true closures. A Java lambda cannot be created in a way that allows it to see changes in the environment in which it was instantiated. If you want to implement a closure that observes or makes changes to its environment, you should simulate it using a regular class. For example:

The above example will not compile for reasons discussed previously. We can work around the compilation error as follows:

The problem is that this breaks the design contract for the IntUnaryOperator interface which states that instances should be functional and stateless. If such a closure is passed to built-in functions that accept functional objects, it is liable to cause crashes or erroneous behavior. Closures that encapsulate mutable state should be implemented as regular classes. For example.

# Using lambda expression with your own functional interface

Lambdas are meant to provide inline implementation code for single method interfaces and the ability to pass them around as we have been doing with normal variables. We call them Functional Interface.

For example, writing a Runnable in anonymous class and starting a Thread looks like:

Now, in line with above, lets say you have some custom interface:

How do you use lambda to give implementation of this interface in your code? Same as Runnable example shown above. See the driver program below:

# Traditional style to Lambda style

Traditional way

Lambda style

  • Remove class name and functional interface body.
  • Optional type declaration
  • Optional parenthesis around parameter, if it is single parameter
  • Optional curly braces, if there is only one line in function body
  • Optional return keyword, if there is only one line in function body

# Lambdas and memory utilization

Since Java lambdas are closures, they can "capture" the values of variables in the enclosing lexical scope. While not all lambdas capture anything -- simple lambdas like s -> s.length() capture nothing and are called stateless -- capturing lambdas require a temporary object to hold the captured variables. In this code snippet, the lambda () -> j is a capturing lambda, and may cause an object to be allocated when it is evaluated:

Although it might not be immediately obvious since the new keyword doesn't appear anywhere in the snippet, this code is liable to create 1,000,000,000 separate objects to represent the instances of the () -> j lambda expression. However, it should also be noted that future versions of Java 1 may be able to optimize this so that at runtime the lambda instances were reused, or were represented in some other way.

1 - For instance, Java 9 introduces an optional "link" phase to the Java build sequence which will provide the opportunity for doing global optimizations like this.

# Lambdas and Execute-around Pattern

There are several good examples of using lambdas as a FunctionalInterface in simple scenarios. A fairly common use case that can be improved by lambdas is what is called the Execute-Around pattern. In this pattern, you have a set of standard setup/teardown code that is needed for multiple scenarios surrounding use case specific code. A few common example of this are file io, database io, try/catch blocks.

Then to call this method with a lambda it might look like:

This is not limited to I/O operations. It can apply to any scenario where similar setup/tear down tasks are applicable with minor variations. The main benefit of this Pattern is code re-use and enforcing DRY (Don't Repeat Yourself).

# return only returns from the lambda, not the outer method

The return method only returns from the lambda, not the outer method.

Beware that this is different from Scala and Kotlin!

This can lead to unexpected behavior when attempting to write own language constructs, as in builtin constructs such as for loops return behaves differently:

In Scala and Kotlin, demo and demo2 would both only print 0 . But this is not more consistent. The Java approach is consistent with refactoring and the use of classes - the return in the code at the top, and the code below behaves the same:

Therefore, the Java return is more consistent with class methods and refactoring, but less with the for and while builtins, these remain special.

Because of this, the following two are equivalent in Java:

Furthermore, the use of try-with-resources is safe in Java:

will print before accept() after close() . In the Scala and Kotlin semantics, the try-with-resources would not be closed, but it would print before accept() only.

# Using lambda expressions & predicates to get a certain value(s) from a list

Starting with Java 8, you can use lambda expressions & predicates.

Example: Use a lambda expressions & a predicate to get a certain value from a list. In this example every person will be printed out with the fact if they are 18 and older or not.

Person Class:

The built-in interface Predicate from the java.util.function.Predicate packages is a functional interface with a boolean test(T t) method.

Example Usage:

The print(personList, p -> p.getAge() >= 18); method takes a lambda expression (because the Predicate is used a parameter) where you can define the expression that is needed. The checker's test method checks if this expression is correct or not: checker.test(person) .

You can easily change this to something else, for example to print(personList, p -> p.getName().startsWith("J")); . This will check if the person's name starts with a "J".

  • () -> { return expression; } // Zero-arity with function body to return a value.
  • () -> expression // Shorthand for the above declaration; there is no semicolon for expressions.
  • () -> { function-body } // Side-effect in the lambda expression to perform operations.
  • parameterName -> expression // One-arity lambda expression. In lambda expressions with only one argument, the parenthesis can be removed.
  • (Type parameterName, Type secondParameterName, ...) -> expression // lambda evaluating an expression with parameters listed to the left
  • (parameterName, secondParameterName, ...) -> expression // Shorthand that removes the parameter types for the parameter names. Can only be used in contexts that can be inferred by the compiler where the given parameter list size matches one (and only one) of the size of the functional interfaces expected.

← Properties Class Basic Control Structures →

  • Java Arrays
  • Java Strings
  • Java Collection
  • Java 8 Tutorial
  • Java Multithreading
  • Java Exception Handling
  • Java Programs
  • Java Project
  • Java Collections Interview
  • Java Interview Questions
  • Spring Boot
  • Java 8 Features - Complete Tutorial

Lambda Expressions

  • Lambda Expression in Java
  • Java - Lambda Expressions Parameters
  • Java Lambda Expression with Collections
  • Java - Lambda Expression Variable Capturing with Examples
  • How to Create Thread using Lambda Expressions in Java?
  • Serialization of Lambda Expression in Java
  • Block Lambda Expressions in Java
  • Match Lambdas to Interfaces in Java
  • Converting ArrayList to HashMap in Java 8 using a Lambda Expression
  • Check if a String Contains Only Alphabets in Java Using Lambda Expression
  • Remove elements from a List that satisfy given predicate in Java

Functional Interfaces

  • Functional Interfaces in Java
  • Java 8 | Consumer Interface in Java with Examples
  • Java 8 | BiConsumer Interface in Java with Examples
  • Java 8 Predicate with Examples
  • Function Interface in Java with Examples
  • Supplier Interface in Java with Examples

Method Reference

  • Method References in Java with examples
  • Converting ArrayList to HashMap using Method Reference in Java 8
  • Java 8 Stream Tutorial
  • Difference Between Streams and Collections in Java
  • Implement Filter Function using Reduce in Java 8 Streams
  • Java Stream API – Filters
  • Parallel vs Sequential Stream in Java
  • Functional Programming in Java 8+ using the Stream API with Example
  • Intermediate Methods of Stream in Java
  • Difference Between map() And flatMap() In Java Stream
  • Array to Stream in Java
  • 10 Ways to Create a Stream in Java

Java Stream Programs

  • Program to convert a Map to a Stream in Java
  • Program to convert Boxed Array to Stream in Java
  • Program to convert Primitive Array to Stream in Java
  • Program to convert a Set to Stream in Java using Generics
  • Program to Convert List to Stream in Java
  • Program to Convert Stream to an Array in Java
  • How to get Slice of a Stream in Java
  • Flattening Nested Collections in Java
  • How to convert a Stream into a Map in Java
  • Find the first element of a Stream in Java

Java Stream Methods

  • Stream forEach() method in Java with examples
  • Stream forEachOrdered() method in Java with examples
  • foreach() loop vs Stream foreach() vs Parallel Stream foreach()
  • Stream of() method in Java
  • Java Stream findAny() with examples
  • Stream anyMatch() in Java with examples
  • Stream allMatch() in Java with examples
  • Stream filter() in Java with examples
  • Stream sorted (Comparator comparator) method in Java
  • Stream sorted() in Java

Comparable and Comparator

  • Comparable vs Comparator in Java
  • Comparator Interface in Java with Examples
  • Why to Use Comparator Interface Rather than Comparable Interface in Java?
  • Sort an Array of Triplet using Java Comparable and Comparator
  • Java Program to Sort LinkedList using Comparable
  • How to Sort HashSet Elements using Comparable Interface in Java?
  • Sort LinkedHashMap by Values using Comparable Interface in Java
  • Sort LinkedHashMap by Keys using Comparable Interface in Java
  • How to Sort LinkedHashSet Elements using Comparable Interface in Java?

Optional Class

  • Java 8 Optional Class
  • Optional ofNullable() method in Java with examples
  • Optional orElse() method in Java with examples
  • Optional ifPresentOrElse() method in Java with examples
  • Optional orElseGet() method in Java with examples
  • Optional filter() method in Java with examples
  • Optional empty() method in Java with examples
  • Optional hashCode() method in Java with examples
  • Optional toString() method in Java with examples
  • Optional equals() method in Java with Examples

Date/Time API

  • New Date-Time API in Java 8
  • java.time.LocalDate Class in Java
  • java.time.LocalTime Class in Java
  • java.time.LocalDateTime Class in Java
  • java.time.MonthDay Class in Java
  • java.time.OffsetTime Class in Java
  • java.time.OffsetDateTime Class in Java
  • java.time.Clock Class in Java
  • java.time.ZonedDateTime Class in Java
  • java.time.ZoneId Class in Java

Java – Lambda Expressions Parameters

Lambda Expressions are anonymous functions. These functions do not need a name or a class to be used. Lambda expressions are added in Java 8. Lambda expressions basically express instances of functional interfaces An interface with a single abstract method is called a functional interface. One example is java.lang.Runnable.

Lambda expressions implement only one abstract function and therefore implement functional interfaces. Predicate interface is an example of a functional interface that has only one abstract method called test().

Illustration:

The above is a functional interface that has one abstract method test receiving only one parameter of type T and returns a boolean value. This method is a generic method that takes a type parameter. This interface can be implemented anywhere in a program using a lambda expression instead of creating classes with multiple functions. For eg, to implement a runnable interface used only for multithreading one needs to implement only a run() method. Then there is the comparable interface which can be implemented using compare() method.

Important points:

java lambda assignment

  • The body of a lambda expression can contain zero, one, or more statements.
  • When there is a 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, then 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.

These are for single – line lambda expressions having void return type.

Type 1: No Parameter.

It takes interface of the following form:

Type 2: Single Parameter.

It is not mandatory to use parentheses if the type of that variable can be inferred from the context

The type and return type of the lambdas are automatically inferred.

Type 3: Multi parameters

Now, we are done with discussing out the theoretical concept, now let us come up with the implementation part. So here primarily we will be discussing out the codes for the above three types as discussed above:

Note: forEach() method is of Iterable interface that is used to iterate through a collection. Here it takes an argument of Consumer type interface. This is a functional interface having only one abstract method called accept(). Since it is a functional interface, a lambda expression can be passed.

Hence, if we do conclude out the above 

Example 1: Lambda expression with no parameters

Example 2: Type 2 Lambda expression with a single parameter

Example 3: Type 3 Lambda expression with multi parameters

Example 4: Lambda expression with two parameters

   

author

Please Login to comment...

Similar reads.

  • java-lambda

Improve your Coding Skills with Practice

 alt=

What kind of Experience do you want to share?

Why Do Local Variables Used in Lambdas Have to Be Final or Effectively Final?

Last updated: January 16, 2024

java lambda assignment

  • >= Java 8
  • Lambda Expressions

announcement - icon

Now that the new version of REST With Spring - “REST With Spring Boot” is finally out, the current price will be available until the 22nd of June , after which it will permanently increase by 50$

>> GET ACCESS NOW

Azure Spring Apps is a fully managed service from Microsoft (built in collaboration with VMware), focused on building and deploying Spring Boot applications on Azure Cloud without worrying about Kubernetes.

The Enterprise plan comes with some interesting features, such as commercial Spring runtime support, a 99.95% SLA and some deep discounts (up to 47%) when you are ready for production.

>> Learn more and deploy your first Spring Boot app to Azure.

And, you can participate in a very quick (1 minute) paid user research from the Java on Azure product team.

Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.

The Jet Profiler was built for MySQL only , so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.

Critically, it has very minimal impact on your server's performance, with most of the profiling work done separately - so it needs no server changes, agents or separate services.

Basically, you install the desktop application, connect to your MySQL server , hit the record button, and you'll have results within minutes:

>> Try out the Profiler

A quick guide to materially improve your tests with Junit 5:

Do JSON right with Jackson

Download the E-book

Get the most out of the Apache HTTP Client

Get Started with Apache Maven:

Get started with Spring and Spring Boot, through the reference Learn Spring course:

>> LEARN SPRING

Building a REST API with Spring?

The AI Assistant to boost Boost your productivity writing unit tests - Machinet AI .

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code. And, the AI Chat crafts code and fixes errors with ease, like a helpful sidekick.

Simplify Your Coding Journey with Machinet AI :

>> Install Machinet AI in your IntelliJ

Get non-trivial analysis (and trivial, too!) suggested right inside your IDE or Git platform so you can code smart, create more value, and stay confident when you push.

Get CodiumAI for free and become part of a community of over 280,000 developers who are already experiencing improved and quicker coding.

Write code that works the way you meant it to:

>> CodiumAI. Meaningful Code Tests for Busy Devs

Looking for the ideal Linux distro for running modern Spring apps in the cloud?

Meet Alpaquita Linux : lightweight, secure, and powerful enough to handle heavy workloads.

This distro is specifically designed for running Java apps . It builds upon Alpine and features significant enhancements to excel in high-density container environments while meeting enterprise-grade security standards.

Specifically, the container image size is ~30% smaller than standard options, and it consumes up to 30% less RAM:

>> Try Alpaquita Containers now.

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth , to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project .

You can explore the course here:

>> Learn Spring Security

DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema .

The way it does all of that is by using a design model , a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.

And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.

>> Take a look at DBSchema

Creating PDFs is actually surprisingly hard. When we first tried, none of the existing PDF libraries met our needs. So we made DocRaptor for ourselves and later launched it as one of the first HTML-to-PDF APIs.

We think DocRaptor is the fastest and most scalable way to make PDFs , especially high-quality or complex PDFs. And as developers ourselves, we love good documentation, no-account trial keys, and an easy setup process.

>> Try DocRaptor's HTML-to-PDF Java Client (No Signup Required)

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

1. Introduction

Java 8 gives us lambdas, and by association, the notion of effectively final variables. Ever wondered why local variables captured in lambdas have to be final or effectively final?

Well, the JLS gives us a bit of a hint when it says “The restriction to effectively final variables prohibits access to dynamically-changing local variables, whose capture would likely introduce concurrency problems.” But, what does it mean?

In the next sections, we’ll dig deeper into this restriction and see why Java introduced it. We’ll show examples to demonstrate how it affects single-threaded and concurrent applications , and we’ll also debunk a common anti-pattern for working around this restriction.

2. Capturing Lambdas

Lambda expressions can use variables defined in an outer scope. We refer to these lambdas as capturing lambdas . They can capture static variables, instance variables, and local variables, but only local variables must be final or effectively final.

In earlier Java versions, we ran into this when an anonymous inner class captured a variable local to the method that surrounded it – we needed to add the final keyword before the local variable for the compiler to be happy.

As a bit of syntactic sugar, now the compiler can recognize situations where, while the final  keyword isn’t present, the reference isn’t changing at all, meaning it’s effectively final. We could say that a variable is effectively final if the compiler wouldn’t complain were we to declare it final.

3. Local Variables in Capturing Lambdas

Simply put, this won’t compile:

start  is a local variable, and we are trying to modify it inside of a lambda expression.

The basic reason this won’t compile is that the lambda is capturing the value of start , meaning making a copy of it. Forcing the variable to be final avoids giving the impression that incrementing start inside the lambda could actually modify the  start method parameter.

But, why does it make a copy? Well, notice that we are returning the lambda from our method. Thus, the lambda won’t get run until after the  start method parameter gets garbage collected. Java has to make a copy of start in order for this lambda to live outside of this method.

3.1. Concurrency Issues

For fun, let’s imagine for a moment that Java did allow local variables to somehow remain connected to their captured values.

What should we do here:

While this looks innocent, it has the insidious problem of “visibility”. Recall that each thread gets its own stack, and so how do we ensure that our while loop sees the change to the  run  variable in the other stack? The answer in other contexts could be using synchronized  blocks or the  volatile  keyword.

However, because Java imposes the effectively final restriction, we don’t have to worry about complexities like this.

4. Static or Instance Variables in Capturing Lambdas

The examples before can raise some questions if we compare them with the use of static or instance variables in a lambda expression.

We can make our first example compile just by converting our start variable into an instance variable:

But, why can we change the value of start here?

Simply put, it’s about where member variables are stored. Local variables are on the stack, but member variables are on the heap. Because we’re dealing with heap memory, the compiler can guarantee that the lambda will have access to the latest value of start.

We can fix our second example by doing the same:

The run  variable is now visible to the lambda even when it’s executed in another thread since we added the  volatile  keyword.

Generally speaking, when capturing an instance variable, we could think of it as capturing the final variable this . Anyway, the fact that the compiler doesn’t complain doesn’t mean that we shouldn’t take precautions, especially in multithreading environments.

5. Avoid Workarounds

In order to get around the restriction on local variables, someone may think of using variable holders to modify the value of a local variable.

Let’s see an example that uses an array to store a variable in a single-threaded application:

We could think that the stream is summing 2 to each value, but it’s actually summing 0 since this is the latest value available when the lambda is executed.

Let’s go one step further and execute the sum in another thread:

What value are we summing here? It depends on how long our simulated processing takes. If it’s short enough to let the execution of the method terminate before the other thread is executed it’ll print 6, otherwise, it’ll print 12.

In general, these kinds of workarounds are error-prone and can produce unpredictable results, so we should always avoid them.

6. Conclusion

In this article, we’ve explained why lambda expressions can only use final or effectively final local variables. As we’ve seen, this restriction comes from the different nature of these variables and how Java stores them in memory. We’ve also shown the dangers of using a common workaround.

As always, the full source code for the examples is available  over on GitHub .

Slow MySQL query performance is all too common. Of course it is.

The Jet Profiler was built entirely for MySQL , so it's fine-tuned for it and does advanced everything with relaly minimal impact and no server changes.

Explore the secure, reliable, and high-performance Test Execution Cloud built for scale. Right in your IDE:

Basically, write code that works the way you meant it to.

AI is all the rage these days, but for very good reason. The highly practical coding companion, you'll get the power of AI-assisted coding and automated unit test generation . Machinet's Unit Test AI Agent utilizes your own project context to create meaningful unit tests that intelligently aligns with the behavior of the code.

Build your API with SPRING - book cover

  • Stack Overflow Public questions & answers
  • Stack Overflow for Teams Where developers & technologists share private knowledge with coworkers
  • Talent Build your employer brand
  • Advertising Reach developers & technologists worldwide
  • Labs The future of collective knowledge sharing
  • About the company

Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Get early access and see previews of new features.

Variable assignment in lambda expression

I have the following fragment of code:

And I'm trying to assign new object to someClass reference in lambda expresion but then I've got error message: "variable used in lambda should be effectively final" .

When I add final to declaration of someClass I got another error "cannot assign value to final variable"

So how can I smartly deal with such assigment in lamdas?

  • variable-assignment

Andrew K.'s user avatar

  • 3 Why do you want to use a lambda? Why not just someClass = optional.isPresent() ? new SomeClass(value) : null; ? –  Jon Skeet Dec 6, 2016 at 20:39
  • 1 Nothing specific. It just seems for me as an elegant way to use ifPresent and lambda when I operate on Optional values.. –  Andrew K. Dec 6, 2016 at 20:47
  • 1 Not really, when you want to modify local variables. That's just not something lambdas support. When a feature doesn't fit, I'd use something else. –  Jon Skeet Dec 6, 2016 at 20:48
  • 1 Thanks, good lesson for me - do not try to use lamdas in every possible place. –  Andrew K. Dec 6, 2016 at 21:08

3 Answers 3

Either, you turn your variable into an instance member, or use an simple if statement:

The last option would be to use an AtomicReference .

Flown's user avatar

  • 1 Correction: you cannot assign to uplevel locals in a lambda. Lambdas can declare their own locals and mutate them. –  Brian Goetz Dec 7, 2016 at 1:47

Do you have to use an OptionalLong , or can you use an Optional<Long> ?

An appropriate idiom for what you want to do is someClass = optional.map(SomeClass::new).orElse(someClass) . However, OptionalLong doesn't have a map(LongFunction) method, for some reason.

Sam's user avatar

AtomicReference can be declared as final and used to hold a reference.

Imposter's user avatar

Your Answer

Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more

Sign up or log in

Post as a guest.

Required, but never shown

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .

Not the answer you're looking for? Browse other questions tagged java lambda java-8 variable-assignment final or ask your own question .

  • Featured on Meta
  • The 2024 Developer Survey Is Live
  • The return of Staging Ground to Stack Overflow
  • The [tax] tag is being burninated
  • Policy: Generative AI (e.g., ChatGPT) is banned

Hot Network Questions

  • Projective space as Grassmannian
  • Does it make sense for giants to use clubs or swords when fighting non-giants?
  • Smallest Harmonic number greater than N
  • XeLaTeX+polyglossia+french+biblatex complain about missing character (U+200B)
  • Is it theoretically possible for the sun to go dark?
  • Inductance after core saturation
  • A trigonometric equation: how hard could it be?
  • A Fantasy story where a man appears to have been crushed on his wedding night by a statue on the finger of which he has put a wedding ring
  • Does retirement (pre-Full Retirement Age) qualify for a special enrollment period for the affordable care act?
  • How to refer to a library in an interface?
  • Divergence of light rays - parallel approximation
  • An application of the (100/e)% rule applied to postdocs: moving on from an academic career, perhaps
  • How do I tell which kit lens option is more all-purpose?
  • Using a transistor to digitally press a button
  • Is 1.5 hours enough for flight transfer in Frankfurt?
  • Should the increasing energy retained in the atmosphere be considered in relation to global warming?
  • Invoking Solana Programs
  • Best way to halve 12V battery voltage for 6V device, while still being able to measure the battery level?
  • Book recommendation introduction to model theory
  • Has ever a country by its own volition refused to join United Nations, or those which havent joined it's because they aren't recognized as such by UN?
  • Advice on DIY Adjusting Rheem Water Heater Thermostat
  • Transformer with same size symbol meaning
  • Why is the Mean Value Theorem called "Gauss's"?
  • Sum of square roots (as an algebraic number)

java lambda assignment

IMAGES

  1. Java 8 Stream And Lambda Tutorial

    java lambda assignment

  2. Lambda Expression Java

    java lambda assignment

  3. Best practices when you use Lambda expressions in Java

    java lambda assignment

  4. Lambda Expression in Java 8

    java lambda assignment

  5. Lambda Expressions In Java (Lambda Expressions)

    java lambda assignment

  6. Learn Java lambda syntax quickly by example

    java lambda assignment

VIDEO

  1. #5 Потоки данных / Java Lambdas / Source Code

  2. #08 AWS Lambda Layer with example

  3. Java Lambda and Stream Full Course

  4. Smart Migration to JDK 8

  5. function_part2 (Anonymous or Lambda function)

  6. Part 3

COMMENTS

  1. How do you assign a lambda to a variable in Java 8?

    Depending on context, adding an explicit {} block around the lambda will help add clarity and may be required. With that, you would get something like: BiFunction<String, Integer, Integer> x = (String k, Integer v) -> {v == null ? 42 : v + 41};

  2. Lambda Expressions (The Java™ Tutorials > Learning the Java Language

    To determine the type of a lambda expression, the Java compiler uses the target type of the context or situation in which the lambda expression was found. It follows that you can only use lambda expressions in situations in which the Java compiler can determine a target type: Variable declarations. Assignments. Return statements. Array initializers

  3. Java Lambda Expressions (With Examples)

    Here is how we can define lambda expression in Java. (parameter list) -> lambda body. The new operator ( ->) used is known as an arrow operator or a lambda operator. The syntax might not be clear at the moment. Let's explore some examples, Suppose, we have a method like this: double getPiValue() {. return 3.1415;

  4. Java Lambda Expressions

    Lambda expressions can be stored in variables if the variable's type is an interface which has only one method. The lambda expression should have the same number of parameters and the same return type as that method. Java has many of these kinds of interfaces built in, such as the Consumer interface (found in the java.util package) used by lists.

  5. Lambda Expressions and Functional Interfaces: Tips and Best ...

    2. Prefer Standard Functional Interfaces. Functional interfaces, which are gathered in the java.util.function package, satisfy most developers' needs in providing target types for lambda expressions and method references. Each of these interfaces is general and abstract, making them easy to adapt to almost any lambda expression.

  6. Lambda Expression in Java

    In Java, Lambda expressions basically express instances of functional interfaces (An interface with a single abstract method is called a functional interface). Lambda Expressions in Java are the same as lambda functions which are the short block of code that accepts input as parameters and returns a resultant value. Lambda Expressions are ...

  7. Java 8 Lambda Expression (with Examples)

    In Java, a lambda expression is an expression that represents an instance of a functional interface. Similar to other types in Java, lambda expressions are also typed, and their type is a functional interface type. To infer the type, the compiler looks at the left side of the assignment in a lambda expression.

  8. Java Lambda Expressions

    Java lambda expressions are Java's first steps into functional programming. This tutorial explains how Java lambda expressions work, how they are defined and how you use them. ... You can assign a lambda expression to a variable and pass it around, like you do with any other object. Here is an example: public interface MyComparator { public ...

  9. Java SE 8: Lambda Quick Start

    The ActionListener example is an interface with only one method. With Java SE 8, an interface that follows this pattern is known as a "functional interface.". Note: This type of interface, was previously known as a Single Abstract Method type (SAM). Using functional interfaces with anonymous inner classes are a common pattern in Java.

  10. Lambda Expressions in Java

    Introduction. Lambda functions have been an addition that came with Java 8, and was the language's first step towards functional programming, following a general trend toward implementing useful features of various compatible paradigms.. The motivation for introducing lambda functions was mainly to reduce the cumbersome repetitive code that went into passing along class instances to simulate ...

  11. Java

    For example, a lambda expression can use an instance or static variable defined by its enclosing class. A lambda expression also has access to (both explicitly and implicitly), which refers to the invoking instance of the lambda expression's enclosing class. Thus, a lambda expression can obtain or set the value of an intrinsic or static ...

  12. Mastering Java Lambda Expressions: From Basics to Advanced

    Understanding Java Lambda Expressions. Lambda expressions, also known as anonymous functions, are a way to represent instances of functional interfaces—an interface with only one abstract method. Lambda expressions offer a concise syntax to create anonymous methods, removing the need to create anonymous inner classes for implementing ...

  13. Java Lambda Expressions Tutorial with examples

    The concept of lambda expression was first introduced in LISP programming language. Java Lambda Expression Syntax. To create a lambda expression, we specify input parameters (if there are any) on the left side of the lambda operator ->, and place the expression or block of statements on the right side of lambda operator.

  14. Guide to Functional Interfaces and Lambda Expressions in Java

    Lambda Expressions in Java Functional Interfaces and Lambda Expressions. Java implements the basic block of functional programming, the pure first-class functions, ... On the right-hand side of the assignment, the compiler expects to find an instantiation of a class that implements StringConcat, not a function. Yet, the code works seamlessly. ...

  15. Java

    The lambda is only "mostly equivalent" to the anonymous class because in a lambda, the meaning of expressions like this, super or toString() reference the class within which the assignment takes place, not the newly created object.. You cannot specify the name of the method when using a lambda—but you shouldn't need to, because a functional interface must have only one abstract method, so ...

  16. #8. Assignment Of Lambda Expression In Java

    Lambda expression is a compact way of implementing a functional interface. This compact form may confuse you. One member has asked me to explain the assignme...

  17. Java

    Java - Lambda Expressions Parameters. Lambda Expressions are anonymous functions. These functions do not need a name or a class to be used. Lambda expressions are added in Java 8. Lambda expressions basically express instances of functional interfaces An interface with a single abstract method is called a functional interface.

  18. Why Do We Need Effectively Final?

    Lambda expressions can use variables defined in an outer scope. We refer to these lambdas as capturing lambdas.They can capture static variables, instance variables, and local variables, but only local variables must be final or effectively final.. In earlier Java versions, we ran into this when an anonymous inner class captured a variable local to the method that surrounded it - we needed ...

  19. Java Lambda Expressions

    Lambda expressions are known to be the biggest feature introduced with Java 8. This was the Java's first step to Functional Programming. As most of us are used to write code using Object Oriented…

  20. What is meant by lambda target type and target type context in Java

    The context in which a lambda expression is used expects a type, which is called the target type. The process of inferring the type of a lambda expression from the context is known as target typing. Consider the following pseudo code for an assignment statement where a variable of type T is assigned a lambda expression: T t = <LambdaExpression>;

  21. java

    The simple answer is you cannot assign local variables from upper levels in lambda expressions. Either, you turn your variable into an instance member, or use an simple if statement: The last option would be to use an AtomicReference. Correction: you cannot assign to uplevel locals in a lambda. Lambdas can declare their own locals and mutate them.