Blog Java Java 8 Features

Mastering Lambda Expressions in Java: A Guide to Conciseness and Functionality

Introduction

Lambda expressions were introduced in Java 8, which revolutionized the way developers can write Java code. They offer a concise and elegant way to express functional logic. In this blog, we’ll dive deep into lambda expressions, their syntax, benefits, and how they integrate seamlessly with functional interfaces.

What are Lambda Expressions?

  • Essentially, a lambda expression is a compact way to implement a functional interface‘s single abstract method.
  • Explain lambda expressions as anonymous functions that can be passed as arguments or assigned to variables
  • Think of it as an anonymous function, a function without a name.
  • Basic Syntax: (parameters) -> { body }

Syntax of Lambda Expressions

A lambda expression in Java has the following syntax:

Java
(parameters) -> { body }
  • Parameters: This is a comma-separated list of input parameters. If there are no parameters, you can use empty parentheses (). If there’s only one parameter, parentheses are optional.
  • Arrow Token ->: This is used to link parameters and the body of the lambda expression.
  • Body: This contains expressions and statements for the lambda expression. If the body has a single statement, the curly braces {} are optional.

Examples of Lambda Expressions

Here are examples of different types of lambda expressions:

  1. No Parameters

A lambda expression with no parameters simply returns a value. For example:

Java
() -> "Hello, World!"

This lambda expression takes no parameters and returns the string “Hello, World!”.

Java
Runnable task = () -> System.out.println("Task running!"); 
  1. Single Parameter

A lambda expression with a single parameter can be written with or without parentheses. For example:

Java
x -> x * x

This lambda expression takes one parameter x and returns the square of x.

Single Parameter With data type:

Java
Comparator<String> strComparator = (String s1) -> s1.length();

Single Parameter Without data type:

Java
Predicate isPositive = n -> n > 0;
  1. Multiple Parameters

A lambda expression with multiple parameters must be enclosed in parentheses. For example:

Java
(a, b) -> a * b

This lambda expression takes two parameters a and b and returns their product.

Java
Function squareFunction = (x, y) -> x * y;

Why Use Lambda Expressions?

  • Concise Code: Lambda expressions streamline code, making it more readable, especially when used with APIs like the Streams API.
  • Functional Programming: They encourage a functional style where you treat functions as first-class citizens.
  • Efficiency with Collections: Lambda expressions work beautifully for iterating, filtering, and transforming collections.

Functional Interfaces: The Key Connection

  • Functional interfaces are the backbone of lambda expressions. They have only one abstract method, serving as the blueprint for the lambda’s implementation
  • Common Examples:
    • Runnable (Task execution)
    • Comparator (Object comparison)
    • Consumer (Accepts an input)
    • Supplier (Provides an output)
    • Predicate (Tests a condition)

Understanding java.util.function for Lambda Expressions:

The java.util.function package in Java 8 contains various functional interfaces that are commonly used with lambda expressions. Some of the interfaces in this package include:

  • Function: Represents a function that accepts one argument and produces a result.
  • Predicate: Represents a predicate (boolean-valued function) of one argument.
  • Consumer: Represents an operation that accepts a single input argument and returns no result.
  • Supplier: Represents a supplier of results.
  • BiFunctionBiPredicateBiConsumer: Represents functions, predicates, and consumers that accept two arguments.

These functional interfaces are widely used in Java 8 and later versions when working with lambda expressions, streams, and other functional programming concepts.

Lambda Expression Examples

Sorting a List:

Java
List<String> names = Arrays.asList("Alice", "Charlie", "Bob");
Collections.sort(names, (s1, s2) -> s1.co
mpareToIgnoreCase(s2));

Filtering Elements:

Java
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
                                   .filter(n -> n % 2 == 0)
                                   .collect(Collectors.toList());

Mapping Data:

Java
List<String> names = Arrays.asList("Alice", "Charlie", "Bob");
List<String> lowerCaseNames = names.stream().map(String::toLowerCase).collect(Collectors.toList());

Return Types in Lambda Expressions

  • The return type of a lambda mirrors the return type of the functional interface’s abstract method.

Lambda Expressions: Beyond the Basics

  • Block Lambdas: For multiple statements: (x, y) -> { System.out.println(x + y); return x * y; }
  • Method References: Shorthand for lambdas that invoke existing methods: ClassName::methodName
Avatar

Neelabh

About Author

As Neelabh Singh, I am a Senior Software Engineer with 6.6 years of experience, specializing in Java technologies, Microservices, AWS, Algorithms, and Data Structures. I am also a technology blogger and an active participant in several online coding communities.

You may also like

Blog Design Pattern

Understanding the Builder Design Pattern in Java | Creational Design Patterns | CodeTechSummit

Overview The Builder design pattern is a creational pattern used to construct a complex object step by step. It separates
Blog Tech Toolkit

Base64 Decode

Base64 encoding is a technique used to encode binary data into ASCII characters, making it easier to transmit data over