Lamda in JAVA8 Interview Q & A

--

What is a lambda expression in Java?

  • Answer: A lambda expression is a concise way to express instances of single-method interfaces (functional interfaces). It provides a clear and more readable syntax for writing anonymous methods.

2. What is a functional interface?

  • Answer: A functional interface is an interface with only one abstract method. Functional interfaces can have multiple default or static methods, but as long as they have a single abstract method, they can be used for lambda expressions.

3. Explain Various Forms of Writing Lambda Expression?

  • Answer: Lambda expressions in Java 8 are a way to represent instances of functional interfaces (interfaces with a single abstract method) in a concise way. Here are the various forms of writing lambda expressions:

1. No Parameters

A lambda expression with no parameters uses empty parentheses.

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

This form is typically used for functional interfaces like Runnable:

Runnable r = () -> System.out.println("Hello, World!");
r.run(); // Outputs: Hello, World!

2. Single Parameter

If the lambda expression has a single parameter, you can omit the parentheses around the parameter.

s -> s.length()

This form is often used with functional interfaces like Function<T, R>:

Function<String, Integer> lengthFunction = s -> s.length();
System.out.println(lengthFunction.apply("Hello")); // Outputs: 5

You can also include the parentheses, which is optional:

(s) -> s.length()

3. Multiple Parameters

If there are multiple parameters, you must use parentheses around the parameters.

(a, b) -> a + b

This form is used with functional interfaces like BiFunction<T, U, R>:

BiFunction<Integer, Integer, Integer> addFunction = (a, b) -> a + b;
System.out.println(addFunction.apply(3, 4)); // Outputs: 7

4. Block Body

If the body of the lambda expression contains multiple statements, you need to enclose them in curly braces and include a return statement if necessary.

(x, y) -> {
int sum = x + y;
return sum;
}

This form can also be used with BiFunction<T, U, R>:

BiFunction<Integer, Integer, Integer> addFunction = (x, y) -> {
int sum = x + y;
return sum;
};
System.out.println(addFunction.apply(3, 4)); // Outputs: 7

5. Type Inference

Java can infer the types of the parameters, so you don’t need to specify them explicitly.

(a, b) -> a + b

If you prefer, you can specify the types explicitly:

(int a, int b) -> a + b

6. Using this Keyword

In a lambda expression, the this keyword refers to the enclosing instance of the class where the lambda is defined.

public class LambdaExample {
public void doSomething() {
Runnable r = () -> {
System.out.println(this.toString());
};
r.run();
}

@Override
public String toString() {
return "LambdaExample instance";
}

public static void main(String[] args) {
new LambdaExample().doSomething(); // Outputs: LambdaExample instance
}
}

7. Capturing Variables

Lambdas can capture (i.e., use) variables from the enclosing scope. These variables must be effectively final.

int number = 5;
Function<Integer, Integer> addNumber = x -> x + number;
System.out.println(addNumber.apply(3)); // Outputs: 8

Summary

Here’s a quick summary of the forms:

  • No parameters: () -> expression
  • Single parameter: parameter -> expression or (parameter) -> expression
  • Multiple parameters: (parameter1, parameter2) -> expression
  • Block body: (parameters) -> { statements; return value; }
  • Type inference: (a, b) -> a + b or (int a, int b) -> a + b

Lambda expressions provide a concise way to represent instances of functional interfaces, and they can be adapted to various use cases in Java 8 and beyond.

4. What is the purpose of the -> symbol in a lambda expression?

  • Answer: The -> symbol separates the lambda expression's parameters from its body. It is often referred to as the arrow operator.

5. Explain the concept of effectively final variables in lambda expressions.

  • Answer: In a lambda expression, you can use local variables that are effectively final (variables whose values do not change after initialization) without explicitly declaring them as final.

6. Can lambda expressions access variables from their surrounding scope?

  • Answer: Yes, lambda expressions can access variables from their surrounding scope. However, these variables must be effectively final or explicitly declared as final.

lambda expressions in Java can access variables from their surrounding scope if those variables are effectively final or explicitly declared as final. An effectively final variable is one whose value does not change after initialization. Here's an example demonstrating how lambda expressions can access variables from their surrounding scope:

public class LambdaScopeExample {

public static void main(String[] args) {
// Variable in the surrounding scope
int outerVariable = 10;

// Lambda expression accessing the variable
MyFunctionalInterface myLambda = () -> {
// Accessing the outerVariable
System.out.println("Value of outerVariable: "
+ outerVariable);
};

// Call the lambda expression
myLambda.myMethod();
}

// Functional interface with a single abstract method
@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
}
}

In this example, the outerVariable is declared outside the lambda expression's body but is accessible inside the lambda. The lambda expression myLambda of type MyFunctionalInterface captures and uses the outerVariable. Note that the outerVariable is effectively final, meaning its value doesn't change after initialization.

It’s important to remember that if you attempt to modify a variable that is not effectively final or explicitly declared as final inside a lambda expression, it will result in a compilation error. For example:

public class LambdaScopeExample {

public static void main(String[] args) {
int outerVariable = 10;

// Compilation error: Variable 'outerVariable' is accessed from within inner class, needs to be final or effectively final
// Uncommenting the line below will result in a compilation error
// outerVariable = 20;

MyFunctionalInterface myLambda = () -> {
// This would cause a compilation error if
//outerVariable is modified above
System.out.println("Value of outerVariable: "
+ outerVariable);
};

myLambda.myMethod();
}

@FunctionalInterface
interface MyFunctionalInterface {
void myMethod();
}
}

In this case, attempting to modify outerVariable after the lambda expression will result in a compilation error because it is no longer effectively final.

7. What is the @FunctionalInterface annotation, and when should it be used?

  • Answer: @FunctionalInterface is an annotation introduced in Java 8 to indicate that an interface is intended to be a functional interface. It is optional but recommended for clarity. The compiler will enforce the single abstract method constraint when this annotation is present.

8. How does the forEach method in the Stream API work with lambda expressions?

  • Answer: The forEach method is used to iterate over elements of a Stream. It takes a lambda expression as an argument, and the expression is applied to each element in the Stream.
import java.util.Arrays;
import java.util.List;

public class ForEachExample {

public static void main(String[] args) {
List<String> fruits = Arrays.asList("Apple", "Banana", "Orange", "Mango");

// Using forEach with a lambda expression
fruits.forEach(fruit ->
System.out.println("Fruit: " + fruit));
}
}

In this example, the lambda expression fruit -> System.out.println("Fruit: " + fruit) is applied to each element in the fruits list, printing each fruit.

Advanced Usage:

You can use the forEach method in combination with other Stream API operations to perform more complex tasks.

Filtering elements before applying forEach

import java.util.Arrays;
import java.util.List;

public class ForEachExample {

public static void main(String[] args) {
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Using forEach with a lambda expression after filtering
numbers.stream()
.filter(n -> n % 2 == 0) // Filter even numbers
.forEach(evenNumber ->
System.out.println("Even Number: " + evenNumber));
}
}

In this example, the filter operation is applied before the forEach method. Only even numbers are processed by the lambda expression in the forEach call.

please go through below link for more details

https://neesri.medium.com/exploring-the-foreach-method-in-java-8-stream-api-3a871cdc07a0

9. What is the difference between a lambda expression and an anonymous class?

  • Answer: Lambda expressions provide a more concise syntax for expressing instances of functional interfaces compared to anonymous classes. Lambda expressions are more readable and less verbose.

10. Explain the concept of method references in Java 8.

  • Answer: Method references allow you to refer to methods or constructors without invoking them. They provide a shorthand notation for writing lambda expressions.

These questions cover various aspects of lambda expressions in Java 8, and understanding them will help you in discussing and implementing lambda expressions in interviews.

--

--

No responses yet