Below is a practical set of Java 8 interview questions and answers, focused on the features most commonly asked: lambdas, functional interfaces, streams, method references, Optional, default/static interface methods, and the Date/Time API.
Java 8 Interview Questions and Answers
1. What are the major features introduced in Java 8?
Java 8 introduced several important features:
Lambda expressions
Functional interfaces
Stream API
Method references
Default and static methods in interfaces
OptionalNew Date and Time API (
java.time)forEach()CompletableFutureBase64 API
2. What is a Lambda Expression?
A lambda expression is a concise way to represent an anonymous function.
Before Java 8:
Runnable r = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};Java 8:
Runnable r = () -> System.out.println("Hello");General syntax:
(parameters) -> expressionor:
(parameters) -> {
// statements
}3. What is a Functional Interface?
A functional interface is an interface containing exactly one abstract method.
Example:
@FunctionalInterface
interface Calculator {
int calculate(int a, int b);
}It can be used with a lambda:
Calculator add = (a, b) -> a + b;
System.out.println(add.calculate(10, 20));Output:
30A functional interface can still contain multiple default and static methods.
4. What are the common built-in Functional Interfaces?
Java 8 provides several in java.util.function.
| Interface | Input | Output | Main method |
|---|---|---|---|
Predicate<T> | T | boolean | test() |
Function<T,R> | T | R | apply() |
Consumer<T> | T | Nothing | accept() |
Supplier<T> | Nothing | T | get() |
UnaryOperator<T> | T | T | apply() |
BinaryOperator<T> | T, T | T | apply() |
Example:
Predicate<Integer> p = n -> n > 10;
System.out.println(p.test(20)); // true5. What is the Stream API?
The Stream API is used to process collections of data in a declarative and functional style.
Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.filter(n -> n % 2 == 0)
.forEach(System.out::println);Output:
2
4A stream doesn't store data itself. It processes data from a source such as a collection.
6. What is the difference between Collection and Stream?
| Collection | Stream |
|---|---|
| Stores data | Processes data |
| Can be traversed multiple times | Usually consumed once |
| Eager operations | Supports lazy operations |
| External iteration common | Internal iteration |
| Data structure | Processing pipeline |
For example:
List<Integer> list = Arrays.asList(1, 2, 3);
Stream<Integer> stream = list.stream();list contains the elements. stream provides a pipeline for processing them.
7. What are intermediate and terminal operations in Streams?
Intermediate operations return another stream and are generally lazy.
Examples:
filter()
map()
flatMap()
distinct()
sorted()
limit()
skip()Terminal operations produce a result or side effect and trigger stream processing.
Examples:
collect()
forEach()
reduce()
count()
findFirst()
anyMatch()Example:
List<String> result = names.stream()
.filter(name -> name.startsWith("A"))
.sorted()
.collect(Collectors.toList());Here filter() and sorted() are intermediate operations, while collect() is terminal.
8. What is the difference between map() and filter()?
filter() decides which elements to keep.
numbers.stream()
.filter(n -> n > 10);map() transforms each element.
numbers.stream()
.map(n -> n * n);Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4);
numbers.stream()
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.forEach(System.out::println);Output:
4
169. What is the difference between map() and flatMap()?
map() performs one-to-one transformation.
List<String> names = Arrays.asList("java", "spring");
names.stream()
.map(String::toUpperCase)
.forEach(System.out::println);flatMap() is useful when each input produces another stream/collection and you want one flattened stream.
List<List<Integer>> list = Arrays.asList(
Arrays.asList(1, 2),
Arrays.asList(3, 4)
);
List<Integer> result = list.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());Result:
[1, 2, 3, 4]10. What is a Method Reference?
Method references are shorthand for lambda expressions that simply call an existing method.
Lambda:
names.forEach(name -> System.out.println(name));Method reference:
names.forEach(System.out::println);Common forms include:
ClassName::staticMethod
object::instanceMethod
ClassName::instanceMethod
ClassName::new11. What is Optional in Java 8?
Optional is a container that may or may not contain a non-null value.
Optional<String> name = Optional.of("Java");
System.out.println(name.get());Instead of directly calling get(), it's usually better to use methods such as:
orElse()
orElseGet()
orElseThrow()
ifPresent()
map()
flatMap()
filter()Example:
String result = name.orElse("Default");It helps make absence explicit and can reduce careless null handling.
12. Difference between orElse() and orElseGet()?
orElse() evaluates its argument eagerly.
value.orElse(getDefaultValue());getDefaultValue() is evaluated even when value is present.
orElseGet() takes a Supplier and evaluates it only when the Optional is empty.
value.orElseGet(() -> getDefaultValue());This distinction matters when generating the default value is expensive or has side effects.
13. Can interfaces have method implementations in Java 8?
Yes. Java 8 introduced default and static methods in interfaces.
interface Vehicle {
default void start() {
System.out.println("Vehicle started");
}
static void info() {
System.out.println("Vehicle interface");
}
}Default methods help evolve interfaces without forcing every existing implementation to implement a newly added method.
14. What happens if two interfaces contain the same default method?
The implementing class must resolve the conflict.
interface A {
default void show() {
System.out.println("A");
}
}
interface B {
default void show() {
System.out.println("B");
}
}
class Test implements A, B {
@Override
public void show() {
A.super.show();
}
}15. What is forEach()?
forEach() performs an action for every element.
List<String> names = Arrays.asList("John", "Sam", "David");
names.forEach(System.out::println);It accepts a Consumer.
16. What is Predicate?
Predicate<T> represents a condition that returns true or false.
Predicate<Integer> even = n -> n % 2 == 0;
System.out.println(even.test(10));Output:
trueCommon methods include:
test()
and()
or()
negate()17. What is Function?
Function<T, R> accepts one argument of type T and produces a result of type R.
Function<String, Integer> length = str -> str.length();
System.out.println(length.apply("Java"));Output:
418. What is Consumer?
A Consumer<T> accepts a value and doesn't return a result.
Consumer<String> print = str -> System.out.println(str);
print.accept("Java 8");A common example is:
list.forEach(System.out::println);19. What is Supplier?
A Supplier<T> takes no arguments and returns a value.
Supplier<Double> random = () -> Math.random();
System.out.println(random.get());20. What is reduce()?
reduce() combines stream elements into a single result.
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream()
.reduce(0, Integer::sum);
System.out.println(sum);Output:
1521. What is the difference between findFirst() and findAny()?
findFirst() returns the first element according to encounter order.
stream.findFirst();findAny() can return any matching element.
stream.findAny();The difference becomes especially relevant with parallel streams, where findAny() may allow more flexible/efficient execution.
22. What is a Parallel Stream?
A parallel stream can process parts of a stream concurrently using the common Fork/Join pool by default.
list.parallelStream()
.forEach(System.out::println);You can also convert an existing stream:
list.stream().parallel();Parallel streams are not automatically faster. Performance depends on data size, operation cost, splitting characteristics, shared state, and available CPU resources.
23. Difference between stream() and parallelStream()?
list.stream();creates a sequential stream.
list.parallelStream();creates a parallel stream.
Parallel processing can improve some CPU-intensive workloads, but it introduces overhead and ordering/concurrency considerations.
24. What is the new Date and Time API?
Java 8 introduced the java.time package as a much cleaner replacement for many uses of old APIs such as Date and Calendar.
Important classes:
LocalDate
LocalTime
LocalDateTime
ZonedDateTime
Instant
Duration
Period
DateTimeFormatterExample:
LocalDate today = LocalDate.now();
LocalDate tomorrow = today.plusDays(1);
System.out.println(today);
System.out.println(tomorrow);25. How do you sort a list using Java 8?
Ascending:
List<Integer> numbers = Arrays.asList(5, 2, 8, 1);
List<Integer> sorted = numbers.stream()
.sorted()
.collect(Collectors.toList());Descending:
List<Integer> sorted = numbers.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());26. How do you remove duplicates using Java 8?
Use distinct():
List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4);
List<Integer> result = numbers.stream()
.distinct()
.collect(Collectors.toList());Result:
[1, 2, 3, 4]27. How do you find duplicate elements using Java 8?
One straightforward approach:
List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 3);
Set<Integer> seen = new HashSet<>();
Set<Integer> duplicates = numbers.stream()
.filter(n -> !seen.add(n))
.collect(Collectors.toSet());
System.out.println(duplicates);For parallel streams, avoid this pattern with an ordinary HashSet because it relies on mutable shared state.
28. How do you find the second-highest number using Java 8?
List<Integer> numbers = Arrays.asList(10, 20, 50, 30, 50, 40);
Integer secondHighest = numbers.stream()
.distinct()
.sorted(Comparator.reverseOrder())
.skip(1)
.findFirst()
.orElseThrow(() -> new IllegalArgumentException("Not enough values"));
System.out.println(secondHighest);Output:
4029. How do you convert a List to a Map?
Suppose:
class Employee {
private int id;
private String name;
// constructors/getters
}Then:
Map<Integer, String> map = employees.stream()
.collect(Collectors.toMap(
Employee::getId,
Employee::getName
));A common follow-up question is: What happens if duplicate keys exist?
Without a merge function, toMap() can throw IllegalStateException. You can supply one:
Map<Integer, String> map = employees.stream()
.collect(Collectors.toMap(
Employee::getId,
Employee::getName,
(oldValue, newValue) -> oldValue
));30. How do you group employees by department?
This is a very common interview coding question.
Map<String, List<Employee>> result =
employees.stream()
.collect(Collectors.groupingBy(Employee::getDepartment));To count employees per department:
Map<String, Long> result =
employees.stream()
.collect(Collectors.groupingBy(
Employee::getDepartment,
Collectors.counting()
));Important coding questions to practice
For Java 8 interviews, make sure you can solve these without much assistance:
Find duplicate elements in a list.
Find the first non-repeated character in a string.
Find the second-highest salary.
Find the highest-paid employee in each department.
Group employees by department.
Count employees in each department.
Sort employees by salary.
Convert
List<Employee>intoMap.Find even/odd numbers using streams.
Find numbers starting with
1.Remove duplicates.
Find max/min values.
Join strings using
Collectors.joining().Partition numbers into even and odd using
partitioningBy().Flatten nested collections using
flatMap().
For 3–5 years of Java experience, interviewers typically go beyond definitions and ask you to write Stream API code involving an Employee object, explain lazy evaluation, map vs flatMap, Optional, collectors, functional interfaces, and parallel streams, and discuss when streams should not be used.