In a Java 8 coding interview, there can be tricky questions that we might not be able to solve if we don't know all possible operations available.
So today we will see all such operations and their usages so that we can apply them on the go. This can help in understanding their usage and implications.
Streams have two types of operations:
Intermediate operations: These return a stream, allowing further processing (e.g., filter, map, flatMap).
Terminal operations: These return a result or affect the original stream (e.g., collect, forEach, reduce).
Certainly! Below is a list of Java 8 Stream API operations, each with a question focusing on achieving a specific goal using the operation, followed by the solution. This format will help in understanding how to use each operation effectively.
Question: Fetch all numbers from a list that are greater than 5.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = numbers.stream()
.filter(n -> n > 5)
.collect(Collectors.toList());
Question: Transform a list of strings into a list of their uppercase versions.
Solution:
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> result = words.stream()
.map(String::toUpperCase)
.collect(Collectors.toList());
// result: ["APPLE", "BANANA", "CHERRY"]
Question: Given a list of lists of strings, flatten them into a single list of strings.
Solution:
List<List<String>> listOfLists = Arrays.asList(
Arrays.asList("one", "two"),
Arrays.asList("three", "four")
);
List<String> result = listOfLists.stream()
.flatMap(Collection::stream)
.collect(Collectors.toList());
// result: ["one", "two", "three", "four"]
Some real-time example:
class Order {
private List<Item> items;
// other fields and methods
public List<Item> getItems() {
return items;
}
}
class Item {
private String name;
// other fields and methods
public String getName() {
return name;
}
}
import java.util.List;
import java.util.stream.Collectors;
public class OrderService {
public List<Item> getAllItems(List<Order> orders) {
return orders.stream()
.flatMap(order -> order.getItems().stream()) // Flattening List<Item>
.collect(Collectors.toList());
}
}
Flatten Items: Use flatMap to transform each Order into a stream of its Item objects. This operation "flattens" the nested structure, converting a Stream<List<Item>> into a Stream<Item>.
Question: Remove duplicates from a list of integers.
Solution:
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]
Question: Sort a list of names in reverse alphabetical order.
Solution:
List<String> names = Arrays.asList("John", "Jane", "Alice", "Bob");
List<String> result = names.stream()
.sorted(Comparator.reverseOrder())
.collect(Collectors.toList());
// result: ["John", "Jane", "Bob", "Alice"]
Question: Print each element in a list while converting them to uppercase.
Solution:
List<String> words = Arrays.asList("apple", "banana", "cherry");
List<String> result = words.stream()
.peek(word -> System.out.println("Original: " + word))
.map(String::toUpperCase)
.collect(Collectors.toList());
// Console output: Original: apple, Original: banana, Original: cherry
// result: ["APPLE", "BANANA", "CHERRY"]
The peek method in Java Streams is primarily used for debugging purposes. It allows you to perform an intermediate operation on each element of the stream without modifying the stream itself.
Question: Fetch the first 3 elements from a list of integers.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = numbers.stream()
.limit(3)
.collect(Collectors.toList());
// result: [1, 2, 3]
Question: Skip the first 4 elements and fetch the remaining elements from a list of integers.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
List<Integer> result = numbers.stream()
.skip(4)
.collect(Collectors.toList());
// result: [5, 6, 7, 8, 9, 10]
Question: Print each element of a list of strings with a prefix "Item: ".
Solution:
List<String> words = Arrays.asList("apple", "banana", "cherry");
words.stream()
.forEach(word -> System.out.println("Item: " + word));
// Console output: Item: apple, Item: banana, Item: cherry
Question: Collect a list of integers into a Set.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 4, 5);
Set<Integer> result = numbers.stream()
.collect(Collectors.toSet());
// result: [1, 2, 3, 4, 5]
Question: Compute the product of all numbers in a list.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> result = numbers.stream()
.reduce((a, b) -> a * b);
// result: Optional[120]
Steps of Reduction:
Start with the first two elements: 1 * 2 = 2
Multiply the result with the next element: 2 * 3 = 6
Multiply the result with the next element: 6 * 4 = 24
Multiply the result with the last element: 24 * 5 = 120
Question: Check if all numbers in a list are positive.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean result = numbers.stream()
.allMatch(n -> n > 0);
// result: true
Question: Check if any number in a list is greater than 10.
Solution:
List<Integer> numbers = Arrays.asList(5, 8, 12, 3);
boolean result = numbers.stream()
.anyMatch(n -> n > 10);
// result: true
Question: Check if no elements in a list are negative.
Solution:
List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean result = numbers.stream()
.noneMatch(n -> n < 0);
// result: true
Question: Find the first element in a list that starts with the letter 'b'.
Solution:
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> result = words.stream()
.filter(word -> word.startsWith("b"))
.findFirst();
// result: Optional[banana]
Question: Find any element in a list that starts with the letter 'c'.
Solution:
List<String> words = Arrays.asList("apple", "banana", "cherry");
Optional<String> result = words.stream()
.filter(word -> word.startsWith("c"))
.findAny();
// result: Optional[cherry]
Question: Find the maximum and minimum value from a list of integers.
Solution:
List<Integer> numbers = Arrays.asList(5, 1, 8, 3, 9);
Optional<Integer> max = numbers.stream()
.max(Integer::compareTo);
// max: Optional[9]
Optional<Integer> min = numbers.stream()
.min(Integer::compareTo);
// min: Optional[1]
Question: Group a list of people by their city of residence.
Solution:
class Person {
private String name;
private String city;
// constructor and getters
public Person(String name, String city) {
this.name = name;
this.city = city;
}
public String getCity() {
return city;
}
}
List<Person> people = Arrays.asList(
new Person("John", "New York"),
new Person("Jane", "London"),
new Person("Jack", "New York")
);
Map<String, List<Person>> result = people.stream()
.collect(Collectors.groupingBy(Person::getCity));
// result: {"New York" -> [John, Jack], "London" -> [Jane]}