25 Must Know Java 8 interview questions with Answers for Experienced Developers
Here are 25 Java 8 interview questions along with answers and code examples tailored for experienced Java developers. These questions cover key features of Java 8 such as streams, lambdas, functional interfaces, and more.
1. What are the major new features in Java 8?
Answer: Java 8 introduced several key features including:
- Lambda expressions
- Stream API
- New Date and Time API
- Default and static methods in interfaces
- Optional class
2. Explain Lambda expressions in Java 8.
Answer: Lambda expressions are a new way to define anonymous functions, which are not bound to an identifier. They are particularly useful in instances where a method takes another method as an argument.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
names.forEach(name -> System.out.println(name));
3. How does the Stream API work in Java 8?
Answer: The Stream API provides a high-level abstraction for processing sequences of elements, supporting sequential and parallel operations. Streams can be created from collections and support operations like map, filter, and reduce.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
List<String> uppercaseNames = names.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
4. What are default methods? Why were they introduced in Java 8?
Answer: Default methods are methods in an interface that have an implementation. They were introduced to provide backward compatibility for old interfaces so new methods can be added without affecting implementing classes.
Code Example:
interface MyInterface {
default void newMethod() {
System.out.println("New default method");
}
}
5. Explain the Optional class in Java 8.
Answer: Optional<T> is a container object which may or may not contain a non-null value. It is used to represent optional values that are either there or not there, helping avoid null checks and NullPointerException.
Code Example:
Optional<String> optional = Optional.of("hello");
optional.ifPresent(System.out::println);
6. What is a functional interface? Can you give an example?
Answer: A functional interface is an interface that contains only one abstract method. They can have multiple default methods. Lambda expressions are often used to provide the implementation of the abstract method of a functional interface.
Code Example:
@FunctionalInterface
interface Converter<F, T> {
T convert(F from);
}
Converter<String, Integer> converter = Integer::valueOf;
int num = converter.convert("5");
7. How can you use method references in Java 8?
Answer: Method references are a shorthand notation of a lambda expression to call a method. There are four types of method references: static methods, instance methods of a particular object, instance methods of an arbitrary object of a particular type, and constructors.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
names.forEach(System.out::println);
8. Explain the differences between map and flatMap in the Stream API.
Answer: map transforms each element of the stream using a function, whereas flatMap can transform each element into zero, one, or multiple elements by flattening the streams resulting from the transformation.
Code Example:
List<List<String>> namesNested = Arrays.asList(
Arrays.asList("John", "Jane"),
Arrays.asList("Jack")
);
List<String> flatNames = namesNested.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
9. What are the advantages of using Streams?
Answer: Streams provide a high level of abstraction for performing operations on collections of data (such as querying, filtering, and transforming), supporting both sequential and parallel execution, improving readability and maintainability.
10. How does forEach differ from the traditional for loop?
Answer: forEach is an internal iterator that abstracts the iteration process, allowing parallel execution and cleaner syntax, whereas a traditional for loop is an external iterator where the iteration details are handled manually by the programmer.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
names.forEach(System.out::println); // forEach
for(String name : names) { // traditional for loop
System.out.println(name);
}
11. What is the Collectors class in Java 8?
Answer: The Collectors class in the java.util.stream package provides reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
String result = names.stream().collect(Collectors.joining(", "));
12. How do you create a parallel stream and what are the considerations for using them?
Answer: A parallel stream can be created by calling parallelStream() on a collection. While parallel streams can provide improved performance by utilizing multiple cores of the computer’s CPU, they are best used when dealing with a large amount of data and operations that can be independently executed. However, care must be taken as not all operations are faster using parallel streams, and improper use can lead to performance degradation and issues like race conditions.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack");
List<String> result = names.parallelStream()
.filter(s -> s.startsWith("J"))
.collect(Collectors.toList());
13. What are the improvements to the Java Collections API in Java 8?
Answer: Java 8 added new methods to the Collections API including forEach, removeIf, replaceAll, and several new methods in Map such as getOrDefault, putIfAbsent, forEach, computeIfAbsent, computeIfPresent, and merge.
14. Describe the reduce operation on a stream.
Answer: The reduce operation combines the elements of a stream to produce a single summary result. This operation takes a binary operator as a parameter and iteratively applies it to combine all elements of the stream.
Code Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);
15. Explain the difference between findFirst and findAny.
Answer: Both findFirst and findAny return an Optional describing some element of the stream. findFirst returns the first element in the stream, which is particularly meaningful in ordered streams. findAny may return any element from the stream, and its behavior is non-deterministic. It is typically used for performance optimization under parallel computation.
Code Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> any = numbers.stream().findAny();
Optional<Integer> first = numbers.stream().findFirst();
16. What are the benefits of using the Optional class?
Answer: The Optional class is used to avoid NullPointerException in Java applications. It provides a clear and explicit way to deal with the absence of a value and helps in writing clean and bug-free code by forcing the developer to actively think about the case where a value may be missing.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("J"))
.collect(Collectors.toList());
17. What is a Predicate in Java 8, and how do you use it?
Answer: A Predicate is a functional interface that represents a boolean-valued function of one argument. It is often used for filtering or matching.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
List<String> filteredNames = names.stream()
.filter(name -> name.startsWith("J"))
.collect(Collectors.toList());
18. How do you handle exceptions in Lambda expressions?
Answer: Handling exceptions in Lambda expressions can be tricky since they do not allow throwing checked exceptions without catching them. Typically, you need to wrap them in a runtime exception or handle them within the lambda.
Code Example:
List<Integer> integers = Arrays.asList(3, 9, 7, 0, 10, 20);
integers.forEach(i -> {
try {
System.out.println(50 / i);
} catch (ArithmeticException e) {
System.err.println("Arithmetic Exception encountered: " + e.getMessage());
}
});
19. Explain the flatMapToInt, flatMapToDouble, and flatMapToLong methods.
Answer: These methods are special cases of flatMap that return an IntStream, DoubleStream, or LongStream respectively. They are used when you have a stream of objects where each object is transformed into a stream of primitive values.
Code Example:
List<String> strings = Arrays.asList("1,2,3", "4,5,6");
int[] numbers = strings.stream()
.flatMapToInt(s -> Arrays.stream(s.split(","))
.mapToInt(Integer::parseInt))
.toArray();
20. How do you sort a stream?
Answer: Streams can be sorted using the sorted() method, which sorts according to natural order unless a comparator is provided.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
List<String> sortedNames = names.stream()
.sorted()
.collect(Collectors.toList());
21. Explain the difference between peek and forEach in a stream.
Answer: peek is mainly used for debugging purposes since it allows viewing each element in the stream without altering it. forEach, on the other hand, is a terminal operation that is generally used to perform an action on each element of the stream.
Code Example:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
numbers.stream()
.peek(num -> System.out.println("Will filter number: " + num))
.filter(x -> x > 3)
.forEach(System.out::println);
22. What is the anyMatch, allMatch, and noneMatch operations?
Answer: These operations are short-circuiting terminal operations to evaluate streams based on certain predicates:
- anyMatch returns true if any elements of the stream match the given predicate.
- allMatch returns true if all elements of the stream match the given predicate.
- noneMatch returns true if no elements of the stream match the given predicate.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Doe");
boolean anyMatch = names.stream().anyMatch(name -> name.startsWith("J"));
boolean allMatch = names.stream().allMatch(name -> name.length() > 3);
boolean noneMatch = names.stream().noneMatch(name -> name.endsWith("x"));
23. How do you use the groupingBy collector?
Answer: groupingBy is used to group elements of the stream by some criteria and collect them into a map.
Code Example:
List<String> names = Arrays.asList("John", "Jane", "Jack", "Diana");
Map<Character, List<String>> groupedByInitial = names.stream()
.collect(Collectors.groupingBy(name -> name.charAt(0)));
24. What are Spliterators in Java 8?
Answer: Spliterator is an interface providing a means to traverse and partition elements of a source. It is designed for parallel iteration, giving more control over the data source compared to Iterator.
Code Example:
Spliterator<String> spliterator = Arrays.asList("apple", "banana", "cherry").spliterator();
spliterator.tryAdvance(System.out::println); // Consumes one element
25. How can you convert an array to a Stream?
Answer: Arrays can be converted to streams using the Arrays.stream method.
Code Example:
int[] numbers = {1, 2, 3, 4, 5};
IntStream numStream = Arrays.stream(numbers);
numStream.forEach(System.out::println);
These questions and examples cover a wide range of Java 8 features, suitable for gauging the expertise of experienced Java developers.
Thanks
Chandan