Interview

10 Java 8 Lambda Interview Questions and Answers

Prepare for your next interview with this guide on Java 8 Lambda expressions, featuring common questions and detailed answers to enhance your understanding.

Java 8 introduced a host of new features, with Lambda expressions being one of the most significant. Lambda expressions enable functional programming in Java, allowing developers to write more concise and flexible code. This feature has revolutionized how Java developers approach tasks such as iteration, filtering, and mapping, making code more readable and maintainable.

This article provides a curated selection of interview questions focused on Java 8 Lambda expressions. By working through these questions and their detailed answers, you will gain a deeper understanding of how to effectively utilize Lambda expressions in real-world scenarios, enhancing your readiness for technical interviews.

Java 8 Lambda Interview Questions and Answers

1. Write a lambda expression that takes two integers and returns their sum.

In Java 8, lambda expressions offer a concise way to represent single-method interfaces. They are useful for defining small code snippets that can be passed as arguments. Here’s an example of a lambda expression that takes two integers and returns their sum:

BinaryOperator<Integer> sum = (a, b) -> a + b;

In this example, BinaryOperator<Integer> is a functional interface that takes two integers and returns an integer. The lambda expression (a, b) -> a + b performs the addition.

2. Use a lambda expression to filter a list of strings that start with a specific letter using the Stream API.

To filter a list of strings that start with a specific letter using a lambda expression and the Stream API, you can use the filter method. This method takes a predicate as an argument, which can be represented using a lambda expression.

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class LambdaExample {
    public static void main(String[] args) {
        List<String> strings = Arrays.asList("apple", "banana", "avocado", "cherry", "apricot");
        char specificLetter = 'a';

        List<String> filteredStrings = strings.stream()
                                              .filter(s -> s.startsWith(String.valueOf(specificLetter)))
                                              .collect(Collectors.toList());

        System.out.println(filteredStrings);
    }
}

In this example, the filter method retains only those strings that start with the specified letter.

3. Create a predicate that checks if a number is even.

A predicate in Java 8 is a functional interface that takes a single argument and returns a boolean. To create a predicate that checks if a number is even, you can use a lambda expression.

Example:

import java.util.function.Predicate;

public class EvenNumberPredicate {
    public static void main(String[] args) {
        Predicate<Integer> isEven = number -> number % 2 == 0;

        System.out.println(isEven.test(4)); // true
        System.out.println(isEven.test(7)); // false
    }
}

4. Write a supplier that returns a random integer.

The Supplier functional interface represents a supplier of results. It has a single abstract method get() that returns a result. To create a supplier that returns a random integer, use the Random class.

Example:

import java.util.Random;
import java.util.function.Supplier;

public class RandomIntegerSupplier {
    public static void main(String[] args) {
        Supplier<Integer> randomIntSupplier = () -> new Random().nextInt();
        System.out.println(randomIntSupplier.get());
    }
}

In this example, the lambda expression calls new Random().nextInt() to generate a random integer.

5. Create a function that converts a string to uppercase.

To create a function that converts a string to uppercase, use the Function interface. This interface represents a function that takes one argument and produces a result.

Example:

import java.util.function.Function;

public class Main {
    public static void main(String[] args) {
        Function<String, String> toUpperCase = (s) -> s.toUpperCase();
        
        String result = toUpperCase.apply("hello world");
        System.out.println(result);  // Output: HELLO WORLD
    }
}

6. Implement a BiFunction that takes two strings and concatenates them.

The BiFunction interface takes two arguments and returns a result. To implement a BiFunction that concatenates two strings, use a lambda expression.

Example:

import java.util.function.BiFunction;

public class Main {
    public static void main(String[] args) {
        BiFunction<String, String, String> concatenate = (str1, str2) -> str1 + str2;
        
        String result = concatenate.apply("Hello, ", "world!");
        System.out.println(result); // Output: Hello, world!
    }
}

7. Define a custom functional interface and use it with a lambda expression.

A functional interface contains exactly one abstract method and can be used with lambda expressions. The @FunctionalInterface annotation indicates that the interface is intended to be a functional interface.

Example:

@FunctionalInterface
interface CustomFunctionalInterface {
    void execute(String message);
}

public class LambdaExample {
    public static void main(String[] args) {
        CustomFunctionalInterface customFunction = (message) -> System.out.println("Message: " + message);
        customFunction.execute("Hello, Lambda!");
    }
}

In this example, CustomFunctionalInterface is a functional interface with a single abstract method execute.

8. Differentiate between intermediate and terminal operations in the Stream API.

The Stream API operations are divided into intermediate and terminal operations. Intermediate operations transform a stream into another stream and are lazy, meaning they do not process elements until a terminal operation is invoked. Examples include filter(), map(), and sorted(). Terminal operations produce a result or a side-effect and mark the end of the stream processing. Examples include forEach(), collect(), and reduce().

Example:

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class StreamExample {
    public static void main(String[] args) {
        List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "David");

        // Intermediate operations: filter and map
        List<String> filteredNames = names.stream()
                                          .filter(name -> name.startsWith("A"))
                                          .map(String::toUpperCase)
                                          .collect(Collectors.toList()); // Terminal operation: collect

        System.out.println(filteredNames); // Output: [ALICE]
    }
}

In this example, filter and map are intermediate operations, while collect is the terminal operation.

9. Describe the purpose and usage of the Optional class.

The Optional class handles cases where a value may or may not be present, providing a way to avoid null pointer exceptions. It is useful in method return types where a value might be missing.

Example:

import java.util.Optional;

public class OptionalExample {
    public static void main(String[] args) {
        Optional<String> optionalValue = getValue();
        
        // Using ifPresent to execute a block of code if the value is present
        optionalValue.ifPresent(value -> System.out.println("Value is: " + value));
        
        // Using orElse to provide a default value if the value is not present
        String result = optionalValue.orElse("Default Value");
        System.out.println("Result is: " + result);
    }

    public static Optional<String> getValue() {
        // Returning an Optional containing a value
        return Optional.of("Hello, World!");
        
        // To return an empty Optional, use Optional.empty()
        // return Optional.empty();
    }
}

10. Explain how collectors work in the Stream API and provide an example.

Collectors in the Stream API perform mutable reduction operations on stream elements, typically accumulating them into a collection or performing aggregation operations. The Collectors class provides static methods that return instances of the Collector interface.

Example:

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class CollectorsExample {
    public static void main(String[] args) {
        List<String> items = Arrays.asList("apple", "banana", "orange", "apple", "banana", "apple");

        // Grouping by item name and counting the occurrences
        Map<String, Long> itemCount = items.stream()
                                           .collect(Collectors.groupingBy(item -> item, Collectors.counting()));

        System.out.println(itemCount);
    }
}

In this example, the stream of items is grouped by the item name, and the occurrences of each item are counted using the groupingBy and counting collectors.

Previous

10 Web Security Interview Questions and Answers

Back to Interview
Next

10 Excel VBA Interview Questions and Answers