0% found this document useful (0 votes)
7 views24 pages

Java 8 Interview Questions

The document provides a comprehensive overview of Java 8 interview questions, covering key features such as Lambda Expressions, Stream API, and Functional Interfaces. It explains concepts like method references, Optional class, and Date-Time API, along with practical examples and code snippets. Additionally, it discusses advantages and disadvantages of various Java 8 features, as well as common stream operations and collectors.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views24 pages

Java 8 Interview Questions

The document provides a comprehensive overview of Java 8 interview questions, covering key features such as Lambda Expressions, Stream API, and Functional Interfaces. It explains concepts like method references, Optional class, and Date-Time API, along with practical examples and code snippets. Additionally, it discusses advantages and disadvantages of various Java 8 features, as well as common stream operations and collectors.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd

Java 8 Interview Questions

1. What features do you know or use in Java 8?

Here you can list down all the key features of Java 8 like,

1. Functional Interface

2. Lambda Expression

3. Stream API

4. CompletableFuture

5. Java DateTime API

6. Method Reference

7. Comparable and Comparator

8. Optional Class

9. Date/Time API

[Link] is Lambda Expression?

Lambda Expression is a short-hand and concise way to write the implementation of a functional
interface (an interface with exactly one abstract method).

Before Java 8
→ We used anonymous classes to implement functional interfaces → very lengthy.

After Java 8
→ Lambda expressions remove boilerplate code and give clean, readable, functional-style code.

Why Lambda? (Interview Answer)

 Removes boilerplate code (no need for anonymous classes).

 Makes code shorter and cleaner.

 Enables functional programming in Java.

 Works beautifully with Streams API.

 Improves readability and maintainability.

 Encourages immutability and side-effect-free functions.

3. What is Stream API in Java 8?

Stream API is introduced in Java 8 and it is used to process


collections of objects with the functional style of coding using
the lambda expression. Unlike Collections, a Stream does not store data it only
processes it.
Features of Streams

 Declarative: Write concise and readable code using functional style.

 Lazy Evaluation: Operations are executed only when needed (terminal operation).

 Parallel Execution: Supports parallel streams to leverage multi-core processors.

 Reusable Operations: Supports chaining of operations like map(), filter(), sorted().

 No Storage: Streams don’t store data; they only process it.

 Single-use
Streams can be consumed once; after terminal operation, they cannot be reused
4. What is Functional Interface in Java 8?
An interface with only one abstract method is known as a
functional interface but there is no restriction, in a
functional interface you can have n number of default
methods and static methods.

5. What is Stream in Java 8?


A stream is a sequence of objects that helps different
methods that can be pipelined to produce the desired
outcome. The features of Java Stream are:
 Stream is not a data structure rather it takes input from
Collections, Arrays, I/O channels.
 Stream doesn't change the original data structure they
only provide the result as per the pipeline methods.
6. When to use map and flatMap?
In Java Streams, map() is used for one-to-one
transformation, where each element is
converted into another single element.
Whereas flatMap() is used when each element
produces multiple elements, and it flattens the
result into a single stream.
For example, if I have a List of Lists, map() will
give me a Stream of Streams, but flatMap() will
merge them into one Stream.
map() performs a one-to-one transformation on
stream elements, meaning each input element
maps to exactly one output element.
flatMap() is used for one-to-many
transformations and then flattens the nested
structure into a single stream.
Internally, flatMap() avoids creating nested
streams like Stream<Stream<T>> and instead
produces a flat Stream<T>, which makes further
stream operations more efficient and readable.
map = transform
flatMap = transform + flatten

Feature map() flatMap()

Output One-to-One One-to-Many

Structur Keeps
Removes nesting
e nesting

Return
Stream Stream (flattened)
Type

Flatten
Transform
Use Case collections/stream
values
s

Using map()
List<String> names = [Link]("Achu", "Torres");

List<Integer> lengths = [Link]()


.map(name -> [Link]())
.toList();

[Link](lengths);
Output:
[4, 6]

List<List<String>> list = [Link](


[Link]("A", "B"),
[Link]("C", "D")
);
List<String> result = [Link]()
.flatMap(l -> [Link]())
.toList();

[Link](result);
Output:

[A, B, C, D]

7. Can we extend a functional interface from


another functional interface?
Yes, we can extend but if you extend that your functional
interface will not act as a functional interface because it
will find multiple abstract methods inside that.
8. What are the advantages of Lambda Expression?
 Avoid writing anonymous implementation
 Saves a lot of code
 Code is directly readable without interpretation
 9. Differentiate Between Comparable and
Comparator in Java.
Comparable is used to define the natural sorting order of
objects within the class itself by implementing the
compareTo() method.
Comparator is used to define custom sorting logic outside
the class using the compare() method, and it allows
multiple sorting strategies.
Comparable (Inside the Class)
class Student implements Comparable<Student> {
int age;

Student(int age) {
[Link] = age;
}

@Override
public int compareTo(Student s) {
return [Link] - [Link]; // natural sorting by age
}
}

[Link](studentList);
Here:

Sorting logic is fixed

Defined inside the Student class


Comparator (Outside the Class)
class AgeComparator implements Comparator<Student>
{
@Override
public int compare(Student s1, Student s2) {
return [Link] - [Link];
}
}
[Link](studentList, new AgeComparator());
Here:

Sorting logic is flexible

Can create multiple comparators (age, name, marks, etc.)


Feature Comparable Comparator

Package [Link] [Link]

Method compareTo() compare()

Sorting Type Natural/default sorting Custom sorting


Feature Comparable Comparator

Location of Logic Inside the class Outside the class

Multiple Sorting ❌ Not possible ✅ Possible

Interface Class implements Separate class or lambda implements


Implementation Comparable Comparator

Why Keeping comparator logic outside?

Comparator logic is kept outside the class to provide flexibility and follow separation of concerns.
The class should not be tightly coupled with a single sorting logic, because in real applications we
may need multiple sorting criteria like name, age, or salary. Keeping it outside allows dynamic and
reusable sorting without modifying the original class.

10. Tell a few functional interfaces which are already there before Java 8?

To answer this question you can tell the below interfaces

 Runnable

 Callable

 Comparator

11. What are all functional interfaces introduced in Java 8?

 Function

 Predicate

 Consumer

 Supplier

 Predicate<T> – tests condition, returns boolean


 Consumer<T> – accepts input, returns nothing
 Supplier<T> – provides output, takes no input
 Function<T,R> – transforms input to output

12. Tell a few stream methods you used in your project?

 filter

 forEach

 sorted

 map

 flatMap

 reduce

 groupingBy
 collect

13. What are the disadvantages of Lambda expression?

 Hard to use without an IDE

 Complex to debug

14. What is Optional Class in Java 8?

 The Optional class used to represent a value that may be present or may not be.

 This class helps in avoiding null pointer exceptions by providing methods to check the
presence of a value before accessing it.

 This helps null values handling more effectively.

Example:

Optional<String> optionalName = [Link]("John");

// Check if value is present


if ([Link]()) {
[Link]("Name is present: " + [Link]());
} else {
[Link]("Name is not present");
}

15. Provide Some Optional Methods in Java 8.

Some Optional methods are described below.

 of: It creates an Optional with a non-null value.

 ofNullable: It creates an Optional with a given nullable value.

 empty: It creates an empty Optional.

 isPresent: This checks whether the Optional contains a non-null value.

 get: It gets the value if present, otherwise it throws an exception i.e.


NoSuchElementException.

 orElse: It returns the value if present, otherwise returns the specified default value.

 orElseGet: It returns the value if present, otherwise it returns the result of invoking the
supplier function.

 orElseThrow: It returns the value if present, otherwise it throws an exception produced by


the provided supplier.

 map: It applies a function to the value if present and return a new Optional with the result,
or return an empty Optional if no value is present.
 filter: It applies a predicate to the value if present and return an Optional with the value if it
matches the predicate, otherwise return an empty Optional.

16. What is Date-Time API in Java 8?

The Date-Time API in Java 8 provides a set of classes for date-time conversions, including timelines
and advanced programming.

 It imports the [Link] package, and this package contains LocalDate, LocalTime,
LocalDateTime, ZonedDateTime, and other classes.

 This API provides better robustness, consistency and thread safety compared to legacy Date
and Calendar classes.

17. What is Optional equals() method in Java?

In Java, the equals() method of the Optional class is used to compare two Optional objects for
equality.

 It returns true if both the Optional objects contains the same value.

 And, it returns false if both does not contain the same value.

Illustration:

import [Link];

public class Main


{
public static void main(String args[])
{
// Creating Optional objects
Optional<String> opt1 = [Link]("Sweta");
Optional<String> opt2 = [Link]("Sweta");
Optional<String> opt3 = [Link]("Dash");

// Comparing Optional objects


[Link]([Link](opt2)); // true
[Link]([Link](opt3)); // false
}
}

18. What is Default Methods In Java 8?

In Java 8, Default methods allows interfaces to have method implementations. This means that
interfaces can contain concrete methods along with the abstract methods. The Default methods are
defined using the default keyword.

Illustration:

interface Vehicle
{
// Abstract method
void start();
// Default method
default void stop()
{
[Link]("Vehicle stopped");
}
}

class Car implements Vehicle


{
@Override
public void start()
{
[Link]("Car started");
}
}

public class Main


{
public static void main(String args[])
{
Car car = new Car();
[Link](); // Output: Car started
[Link](); // Output: Vehicle stopped
}
}

For more details, refer to this article: Default Methods In Java 8

19. How are functional interfaces and Lambda Expressions related?

Functional interfaces in Java are interfaces that only contains one abstract method.

 Lambda expressions provide a simple way to implement functional interfaces.

 Lambda expressions can be used wherever functional interfaces are needed.

 This allows us to write expressive and concise code.

Illustration:

// Functional interface
interface MyFunctionalInterface {
void myMethod();
}

public class Main {


public static void main(String[] args) {
// Lambda expression for implemention of the functional interface
MyFunctionalInterface myLambda = () -> [Link]("Hello Lambda!");
// calling method, using lambda expression
[Link]();
}
}

20. What is ArrayList forEach() method in Java?

In Java, the forEach() method is used to iterate over each ArrayList element.

 It performs specified operation for each element.

 It simplifies iteration and shortens the code.

 It takes a Consumer as a parameter, which represents the action to be performed on each


element.

ArrayList<Integer> numbers = new ArrayList<>();


[Link](1);
[Link](2);
[Link](3);

[Link](num -> [Link](num));

Output:
1
2
3

21. Key advantages of Stream API include:

 Lazy evaluation for better performance

 Parallel processing capabilities

 Functional programming approach

 Cleaner, more readable code

22. Explain method references in Java 8. What are different types?

Method references provide shorthand for lambda expressions calling existing methods.

Types:

 Static: Integer::parseInt

 Instance: String::length

 Constructor: ArrayList::new

23. What are collectors in Java 8? Explain commonly used collectors.

Collectors accumulate stream elements into collections or other data structures.

Common collectors:
// toList()

List<String> list = [Link]([Link]());

// groupingBy()

Map<String, List<Employee>> byDept =

[Link]().collect([Link](Employee::getDepartme

24. Filter employees with salary greater than 50000 using Stream API

List<Employee> highSalaryEmployees = [Link]()

.filter(emp -> [Link]() > 50000)

.collect([Link]());

25. Find the second highest salary from employee list using Stream API

Optional<Double> secondHighest = [Link]()

.mapToDouble(Employee::getSalary)

.distinct()

.sorted()

.skip([Link]() - 2)

.findFirst();

26. Group a list of products by category using Stream API

Map<String, List<Product>> productsByCategory = [Link]()

.collect([Link](Product::getCategory));

27. Remove duplicate elements from a list using Stream API

List<String> uniqueNames = [Link]()

.distinct()

.collect([Link]());

28. Convert list of strings to uppercase and collect as comma-separated string

String result = [Link]()

.map(String::toUpperCase)

.collect([Link](", "));

29. How do you handle exceptions in Stream operations?

Wrap checked exceptions in runtime exceptions or use helper methods:

// Helper method approach


public static <T, R> Function<T, R> wrap(CheckedFunction<T, R> function) {

return t -> {

try {

return [Link](t);

} catch (Exception e) {

throw new RuntimeException(e);

};

30. Implement a solution to find employees working in multiple departments

Map<String, Long> employeeDeptCount = [Link]()

.collect([Link](

Employee::getName,

[Link]()

))

.entrySet().stream()

.filter(entry -> [Link]() > 1)

.collect([Link](

[Link]::getKey,

[Link]::getValue

));

31. Explain the forEach method in Java 8.

Answer: The forEach method is part of the Iterable interface and is used to iterate over each element
of a collection. It is often used with lambda expressions.

Example:

List<String> list = [Link]("a", "b", "c"); [Link](item -> [Link](item));

32. What is the difference between findFirst and findAny?


Answer: Both findFirst and findAny are terminal operations used to retrieve elements from a Stream.
findFirst returns the first element in the Stream, while findAny can return any element, particularly
useful in parallel streams for better performance.

Example:

List<String> list = [Link]("a", "b", "c"); Optional<String> first = [Link]().findFirst();


Optional<String> any = [Link]().findAny();

33. How do you create an infinite stream in Java 8?

Answer: Infinite streams can be created using [Link] or [Link].

Example:

Stream<Integer> infiniteStream = [Link](0, n -> n + 2);


[Link](10).forEach([Link]::println);

34. Filter numbers > 5 from an ArrayList using Streams(IBS Software)

I converted the ArrayList into a stream using [Link](). Then I used filter() which takes a Predicate
functional interface. Inside filter, I used a lambda expression n -> n > 5 to filter elements greater than
5. Finally, I collected the filtered elements into a new list using collect([Link]()).”

Method 1: Without Lambda (Using Anonymous Class)

Method 2: Without Lambda (Using Separate Predicate Class)


Yes, since filter() accepts a Predicate functional interface, I can replace the lambda with an
anonymous class implementation of Predicate or use a method reference.

35. Stream methods accept Functional Interface objects as parameters?

Yes, Collection → Stream → Functional Interface Logic → Result

[Link]()
.filter(n -> n > 5) // Predicate
.map(n -> n * 2) // Function
.forEach([Link]::println); // Consumer

Each step accepts a functional interface object.

36. Can Arrays be used with Streams?

All classes that implement Collection have the stream() method. That means: ArrayList, LinkedList,
HashSet, TreeSet, Vector, Stack. All of these support .stream().

Map does NOT directly have stream()

[Link]().stream()
[Link]().stream()
[Link]().stream()

Arrays are NOT Collections. So this will NOT work:

int[] arr = {1,2,3};


[Link](); ❌

Instead use:

[Link](arr)

No, streams can be used with any Collection implementation like List, Set, and Queue because the
stream() method is defined in the Collection interface as a default method. For arrays, we use
[Link](). For Maps, we stream keySet(), values(), or entrySet().

37. How Stream Method Exists?

In Java 8, stream() was added as a default method inside the Collection interface.
So any class implementing Collection automatically gets it.

That’s why it works on all lists, sets, etc.

38. Why Do We Write Predicate<Integer>? Why “Integer”?

That <Integer> tells Java: “Hey, this Predicate will work on Integer type inputs.”

So internally it becomes: boolean test(Integer t);

If you wrote: Predicate<String> p = s -> [Link]() > 3;

Now the method becomes: boolean test(String s);

Same interface, different type. That’s the power of generics.

What Happens If You Don’t Mention <Integer>?

You can technically write:

Predicate predicate = value -> value != null;

But this is BAD practice because:

 It becomes raw type

 Type safety is lost

 Compiler warnings appear

 Not interview-friendly

39. How Lambda Knows the Type Automatically? [Link]().filter(n -> n > 5); You didn’t write:

(Integer n) -> n > 5? When we pass lambda like n -> n > 5, we don’t write <Integer>, so how does
Java know the type?

Still Java understands n is Integer.


Why? Exactly. Because of Type Inference.

Because:

 list is List<Integer>

 filter() expects Predicate<Integer>

 So compiler infers n is Integer

This is called Context-based Type Inference

Predicate is a generic functional interface where T represents the input type. When we write
Predicate<Integer>, it means the test() method will accept an Integer parameter. Lambda expressions
provide the implementation of the functional interface method

When Do We Explicitly Write <Integer>?

You write it when you create the functional interface yourself.


Predicate<Integer> p = x -> x > 5;

Here you MUST specify <Integer> because:

 Compiler has no surrounding context

 It needs to know what type x is

Otherwise this becomes ambiguous.

In lambda expressions, we usually don’t specify <Integer> because Java uses type inference. The
compiler determines the target functional interface type from the context, such as the Stream type
and method signature. For example, filter() expects a Predicate<T>, so if the stream is
Stream<Integer>, the lambda is treated as Predicate<Integer> automatically

40. Why .collect([Link]()); ?

After .filter(), what do you get? You get a Stream, NOT a List.

Streams are just pipelines — they don’t store data.

So if you want actual results in a collection (like List), you must convert the stream back.

That’s where: .collect([Link]());

41. What is collect()?

collect() is a terminal operation of Stream.

Meaning:

 It ends the stream pipeline.

 It produces a final result.


<R> R collect(Collector<? super T, A, R> collector)
It accepts a Collector object.

Collectors is a utility class.

toList() is a static method that returns a Collector.

42. Why We Need collect()?

Because Streams are:

 Lazy

 Do not store data

 Only process data

Without terminal operation, nothing runs.


This does NOTHING until a terminal operation is called. Execution happens ONLY when a terminal
operation is called.

Java does NOT:

 iterate the list

 apply the filter

 produce results

Instead, it just builds a pipeline description. Think of it like: “Okay noted. If someone asks for the
result later, THEN I’ll filter.” No terminal operation = No execution.

Terminal operations include:

 collect()

 forEach()

 count()

 reduce()

 findFirst()

collect() is a terminal operation that transforms the processed stream elements into a collection.
[Link]() provides a Collector implementation that accumulates the stream elements into a
List.”

43. Are stream operations executed immediately?


No, stream intermediate operations like filter and map are lazy. They only execute when a terminal
operation such as collect(), forEach(), or count() is invoked.

44. What will happen here?

[Link]()
.filter(n -> n > 5)
.filter(n -> n % 2 == 0)
.count();

Will Java:
A) First filter entire list, then second filter
B) Process element-by-element through the pipeline

B) Java does NOT:

 First run filter1 on the whole list

 Then run filter2 on the filtered list

That would be inefficient and require multiple passes.

Instead, streams use pipelined (fused) processing.

So processing is:

Element → filter1 → filter2 → terminal op

Not:

Full list → filter1 → new list → filter2

Stream operations are lazily evaluated and processed element-by-element through a pipeline. Each
element passes through all intermediate operations like filter and map before moving to the next
element, instead of processing the entire stream in separate passes.

45. Difference between forEach() in Stream vs forEach() in Collection.

[Link] are declarative. Explain.

You tell Java WHAT result you want, not HOW to get it step-by-step. Java (Stream API) handles the
internal iteration, looping, and processing for you.

Imperative Style = HOW (traditional Java)

You control every step manually.

Example: Filter numbers > 5 (without streams)

Here you are telling Java:


 Create list

 Loop manually

 Check condition

 Add element

This is:

Step-by-step instructions (HOW to do it)

Declarative Style = WHAT (Streams)

Now same logic using Streams:

Here you are NOT saying:

 how to loop

 how to store

 how to iterate

You are just declaring:

“Give me elements greater than 5”

That’s it. Java handles the loop internally. So iteration exists — but hidden.

Streams are declarative because we specify what transformation we want (like filter, map, collect)
instead of writing explicit loops that define how to iterate and process elements. The Stream API
handles the internal iteration and execution.

47. How are lambdas implemented internally?

Lambdas in Java are implemented using the invokedynamic instruction introduced in Java 7. Instead
of generating a separate anonymous class file, the JVM creates the lambda implementation
dynamically at runtime using LambdaMetafactory. This reduces class loading overhead and improves
performance compared to anonymous inner classes.

48. What is lazy evaluation in Java Streams?

Lazy evaluation means:

“Don’t do the work until absolutely necessary.” Execution is delayed until the result is actually
[Link] does NOT run immediately.

Lazy evaluation means that intermediate stream operations like filter and map do not execute
immediately. They are only executed when a terminal operation such as collect or toList is called.
This allows Streams to optimize processing and avoid unnecessary computation.
Why Streams Are Lazy?

Because of performance optimization.

49. Why Lazy Evaluation Is Powerful?

 Improves performance

 Avoids unnecessary computation

 Enables infinite streams

 Supports short-circuit operations

Infinite stream — but works because of laziness.

50. Why Vertical Processing is Powerful

1️⃣ Performance Optimization

Stops early when possible (like limit, findFirst, anyMatch)

2️⃣ Less Memory Usage

No need to create multiple intermediate collections.

3️⃣ Works perfectly with Lazy Evaluation

Intermediate operations are executed only when needed.

51. Option A:

 First filter ALL elements

 Then map ALL elements

 Then limit

Option B:

 Take one element

 Pass it through filter → map → limit

 Then next element

Java chooses Option B.

Why?

Because it's lazy. Because streams are lazy, they:

 Do not precompute intermediate results


 Do not create temporary collections

 Do not fully execute each stage separately

Instead they:

Process elements only when needed and only as much as needed.

This leads naturally to:

Vertical (element-by-element) processing.

If it was not lazy:

 It would filter everything first.

 Then map everything.

 Then limit.

That would waste work.

Lazy evaluation allows streams to combine intermediate operations into a single pipeline and process
elements one-by-one only when a terminal operation demands the result.

That’s why:

 Lazy → Vertical processing

 Lazy → Short-circuiting (limit, findFirst, anyMatch)

 Lazy → Performance optimization

52. Do streams execute without terminal operations?

No. Stream intermediate operations like filter and map are lazy and only build a pipeline. The actual
computation happens only when a terminal operation such as collect, toList, forEach, or count is
invoked.

53. Will it work twice or throw exception? And why?

No. A stream cannot be reused after a terminal operation because it gets consumed and closed.
Attempting to reuse it results in an IllegalStateException stating that the stream has already been
operated upon or closed.

A Java Stream can be consumed only ONCE. Streams are single-use objects.

Once a terminal operation runs:

 The stream is considered consumed

 The pipeline is closed


 You cannot reuse it

54. What is groupingBy vs partitioningBy

groupingBy is used to classify stream elements into multiple groups based on a key function, while
partitioningBy is a special case of grouping that splits elements into exactly two groups based on a
boolean predicate.

They are static factory methods of the Collectors class that return Collector objects, which are used
inside the collect() terminal operation to accumulate stream results.

groupingBy groups elements based on a classification function.

It creates a Map<K, List<V>>

partitioningBy splits elements into TWO groups based on a boolean condition.

It ALWAYS returns: Map<Boolean, List<T>>

Only two keys:

 true

 false

Feature groupingBy partitioningBy

Group count Multiple groups Only 2 groups


Feature groupingBy partitioningBy

Key type Any type (String, Integer, etc.) Boolean (true/false)

Classifier Function<T, K> Predicate

Flexibility Very flexible Limited but optimized

Return type Map<K, List> Map<Boolean, List>

55. When Should You Use Each?

Use groupingBy when:

 More than 2 categories

 Custom keys

 Complex classification

Example:

 Group employees by department

 Group students by grade

 Group strings by length

Use partitioningBy when:

 Only TRUE/FALSE split needed

 Binary condition

 More readable than filter + two lists

Example:

 Pass/Fail

 Adult/Minor

 Even/Odd (boolean condition)

56. Can partitioningBy be replaced with groupingBy?

Yes, but partitioningBy is more efficient and clearer when the classifier is a boolean predicate, since it
directly creates a Map<Boolean, List<T>> instead of arbitrary grouping keys.

57. What is Optional in Java?

Optional is used primarily as a return type to represent absence of value, avoid NullPointerException,
improve code readability, and enforce explicit null handling using functional methods like map,
orElse, and orElseThrow.

Optional is a container object introduced in Java 8 that may or may not contain a non-null value.

It is used to avoid NullPointerException (NPE) and handle missing values in a safe and expressive way.
Before Java 8:

If getName() returns null → crash.

With Optional:

Now it is safe. No crash. Optional is a null-safe wrapper that forces developers to handle absence of
value explicitly.

58. When NOT to Use Optional?

Do NOT use Optional:

 In fields (class variables)

 In method parameters

 In DTOs / Entities (like JPA entities)

Optional is mainly for return types, not storage.

You might also like