fbpx

Top 100 Java Streams Interview Questions and Answers

Top 100 Java Streams Interview Questions and Answers

Contents show

1. What is a Java Stream?

Answer:

A Java Stream is a sequence of elements that supports various operations for processing data. It doesn’t store data, but provides a pipeline for transforming, filtering, and aggregating elements. Streams can operate in parallel, enhancing performance.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().mapToInt(Integer::intValue).sum();

2. What is the difference between a Stream and a Collection?

Answer:

A Collection is an in-memory data structure that stores and manages a group of objects. In contrast, a Stream is a sequence of data elements that can be processed in a pipeline fashion. Streams are not storage entities like collections.

Reference:

Official Java Documentation on Streams


3. How do you create a Stream in Java?

Answer:

You can create a Stream from various sources like collections, arrays, or by using the Stream.of() method. For example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Stream<String> stream = names.stream();

4. What are the different types of Stream operations?

Answer:

Stream operations are divided into two categories: Intermediate and Terminal operations. Intermediate operations transform or filter the elements and return a new Stream. Terminal operations produce a result or side-effect and close the Stream.

Reference:

Stream Operations in Java Documentation


5. What is lazy evaluation in Streams?

Answer:

Lazy evaluation means that the elements in a Stream are not processed until a terminal operation is called. This allows for more efficient use of resources, as only the necessary elements are operated upon.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> stream = numbers.stream().map(n -> {
    System.out.println("Mapping: " + n);
    return n * 2;
});

6. How do you filter elements in a Stream?

Answer:

You can filter elements using the filter() method, which takes a Predicate. It evaluates each element and retains only those that satisfy the predicate.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> filteredNames = names.stream().filter(s -> s.startsWith("A")).collect(Collectors.toList());

7. What is the difference between map() and flatMap()?

Answer:

  • map() transforms each element in a Stream into another element.
  • flatMap() transforms each element into zero or more elements, and flattens them into the resulting Stream.

Example:

List<List<Integer>> nestedNumbers = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4, 5));
List<Integer> flattenedNumbers = nestedNumbers.stream().flatMap(List::stream).collect(Collectors.toList());

8. How do you find the maximum element in a Stream?

Answer:

You can use the max() method, which takes a Comparator. It returns an Optional containing the maximum element, or an empty Optional if the Stream is empty.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> maxNumber = numbers.stream().max(Integer::compare);

9. What is the purpose of the reduce() operation?

Answer:

The reduce() operation combines all elements of a Stream into a single value. It takes an initial value (or identity) and a BinaryOperator, which combines two elements.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().reduce(0, Integer::sum);

10. How do you perform parallel processing with Streams?

Answer:

You can use the parallelStream() method on collections to process elements in parallel. This allows for concurrent execution and can improve performance for large datasets.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.parallelStream().forEach(System.out::println);

11. How do you convert a Stream to a List?

Answer:

You can use the collect() method to convert a Stream to a List. For example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> numberList = numbers.stream().collect(Collectors.toList());

Reference:

Official Java Documentation on Collectors


12. What is the purpose of forEach() in Streams?

Answer:

The forEach() method is a terminal operation that applies an action to each element in the Stream. It is typically used for side effects, like printing elements or updating external state.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.stream().forEach(System.out::println);

13. How do you use distinct() in a Stream?

Answer:

The distinct() method filters out duplicate elements in a Stream, ensuring that only unique elements are processed.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 2, 3, 3, 4, 5);
List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());

14. What is the purpose of skip() in a Stream?

Answer:

The skip(n) method skips the first n elements in a Stream. It’s useful for ignoring a certain number of initial elements.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> skippedNumbers = numbers.stream().skip(2).collect(Collectors.toList());

15. How do you use limit() in a Stream?

Answer:

The limit(n) method restricts the Stream to a maximum of n elements. It’s helpful for processing only a certain number of elements.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limitedNumbers = numbers.stream().limit(3).collect(Collectors.toList());

16. What is the purpose of sorted() in a Stream?

Answer:

The sorted() method orders the elements of a Stream. It can use natural ordering or a custom Comparator.

Example:

List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());

17. How do you perform aggregation using Streams?

Answer:

You can use operations like sum(), average(), min(), and max() in conjunction with Collectors to aggregate data in a Stream.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.stream().mapToInt(Integer::intValue).sum();

18. What is the purpose of anyMatch(), allMatch(), and noneMatch() in Streams?

Answer:

  • anyMatch(predicate): Checks if any element in the Stream matches the given predicate.
  • allMatch(predicate): Checks if all elements in the Stream match the given predicate.
  • noneMatch(predicate): Checks if none of the elements in the Stream match the given predicate.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0);

19. What is the purpose of findFirst() and findAny() in Streams?

Answer:

  • findFirst() returns the first element in the Stream, or an empty Optional if the Stream is empty.
  • findAny() returns any element in the Stream, or an empty Optional if the Stream is empty. It may return different elements in parallel streams.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> first = numbers.stream().findFirst();
Optional<Integer> any = numbers.parallelStream().findAny();

20. How do you convert a Stream of objects to an array?

Answer:

You can use the toArray() method to convert a Stream to an array. For example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer[] numberArray = numbers.stream().toArray(Integer[]::new);

Reference:

Official Java Documentation on Stream.toArray()


21. What is the purpose of peek() in Streams?

Answer:

The peek() method allows you to perform a non-destructive operation on each element in the Stream, without affecting the Stream’s elements. It’s useful for debugging or logging.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> upperCaseNames = names.stream()
                                   .map(String::toUpperCase)
                                   .peek(System.out::println)
                                   .collect(Collectors.toList());

22. How do you handle exceptions in a Stream?

Answer:

You can use try-catch blocks within the map() or filter() operations. Alternatively, you can use flatMap() to handle exceptions and return an empty Stream for failed elements.

Example:

List<String> numbers = Arrays.asList("1", "2", "three", "4", "5");
List<Integer> validNumbers = numbers.stream()
                                    .flatMap(s -> {
                                        try {
                                            return Stream.of(Integer.parseInt(s));
                                        } catch (NumberFormatException e) {
                                            return Stream.empty();
                                        }
                                    })
                                    .collect(Collectors.toList());

23. What is the purpose of groupingBy() in Streams?

Answer:

The groupingBy() collector is used for grouping elements based on a specified property or criteria. It returns a Map where the keys are the grouping criteria and the values are Lists of elements.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna", "Alex");
Map<Character, List<String>> groupedNames = names.stream().collect(Collectors.groupingBy(s -> s.charAt(0)));

Reference:

Official Java Documentation on Collectors.groupingBy()


24. How do you concatenate Streams?

Answer:

You can use the Stream.concat() method to concatenate two streams. It takes two Stream objects and returns a new Stream containing elements of both.

Example:

Stream<Integer> stream1 = Arrays.asList(1, 2, 3).stream();
Stream<Integer> stream2 = Arrays.asList(4, 5, 6).stream();
Stream<Integer> combinedStream = Stream.concat(stream1, stream2);

Reference:

Official Java Documentation on Stream.concat()


25. What is the purpose of flatMap() in Streams?

Answer:

The flatMap() operation is used to flatten nested collections or streams into a single stream of elements. It’s particularly useful when dealing with elements that contain multiple items.

Example:

List<List<Integer>> nestedList = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4));
List<Integer> flattenedList = nestedList.stream().flatMap(Collection::stream).collect(Collectors.toList());

26. How do you use reduce() in Streams?

Answer:

The reduce() operation combines the elements of a Stream into a single result. It takes an identity value and a BinaryOperator, and performs a left-associative reduction.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream().reduce(Integer::sum);

27. What is the purpose of min() and max() in Streams?

Answer:

  • min(Comparator) returns the minimum element in the Stream based on the provided Comparator.
  • max(Comparator) returns the maximum element in the Stream based on the provided Comparator.

Example:

List<Integer> numbers = Arrays.asList(3, 1, 4, 1, 5, 9, 2, 6);
Optional<Integer> min = numbers.stream().min(Integer::compare);
Optional<Integer> max = numbers.stream().max(Integer::compare);

28. How do you perform parallel processing with Streams?

Answer:

You can use the parallelStream() method to convert a Stream into a parallel Stream, allowing for concurrent processing of elements.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int sum = numbers.parallelStream().mapToInt(Integer::intValue).sum();

29. What is the purpose of collect() in Streams?

Answer:

The collect() method is a terminal operation that accumulates elements from a Stream into a collection or other data structure.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> nameList = names.stream().collect(Collectors.toList());

30. How do you create an infinite Stream in Java?

Answer:

You can use methods like Stream.iterate() or Stream.generate() to create infinite Streams.

Example:

Stream<Integer> infiniteStream = Stream.iterate(0, n -> n + 1);

31. What is the purpose of toArray() in Streams?

Answer:

The toArray() method is used to convert the elements of a Stream into an array. It can produce both primitive and object arrays.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Integer[] numberArray = numbers.stream().toArray(Integer[]::new);

32. How do you create a Stream from an array in Java?

Answer:

You can use the Arrays.stream() method to create a Stream from an array.

Example:

String[] namesArray = {"Alice", "Bob", "Charlie"};
Stream<String> namesStream = Arrays.stream(namesArray);

33. What is the purpose of of() in the Stream interface?

Answer:

The Stream.of() method allows you to create a Stream from a sequence of elements. It can take any number of arguments and create a Stream of those elements.

Example:

Stream<Integer> numbersStream = Stream.of(1, 2, 3, 4, 5);

34. How do you use IntStream and LongStream in Java?

Answer:

IntStream and LongStream are specialized Stream interfaces for handling primitive integer and long values. They provide specialized operations for these types.

Example:

IntStream intStream = IntStream.range(1, 6); // Creates a stream of ints from 1 to 5
LongStream longStream = LongStream.of(10, 20, 30, 40, 50); // Creates a stream of longs

35. What is the purpose of boxed() in Streams?

Answer:

The boxed() method is used to convert a Stream of primitive types (like IntStream, DoubleStream, etc.) into a Stream of boxed objects (like Stream<Integer>, Stream<Double>, etc.).

Example:

IntStream intStream = IntStream.range(1, 6);
Stream<Integer> boxedStream = intStream.boxed();

36. How do you generate a Stream of random numbers?

Answer:

You can use Random.ints() or Random.doubles() to generate a Stream of random numbers.

Example:

Random random = new Random();
IntStream randomInts = random.ints(5, 1, 11); // Generates 5 random integers between 1 and 10

Reference:

Official Java Documentation on Random.ints()


37. What is the purpose of takeWhile() and dropWhile() in Streams?

Answer:

  • takeWhile(predicate): Returns a Stream of elements until the first element that fails the given predicate.
  • dropWhile(predicate): Returns a Stream of elements after the first element that fails the given predicate.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 2, 1);
List<Integer> takenWhile = numbers.stream().takeWhile(n -> n < 4).collect(Collectors.toList());
List<Integer> droppedWhile = numbers.stream().dropWhile(n -> n < 4).collect(Collectors.toList());

38. What is the purpose of forEachOrdered() in Streams?

Answer:

The forEachOrdered() method ensures that the elements of a Stream are processed in the order of their encounter, which is important for parallel processing.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
names.parallelStream().forEachOrdered(System.out::println);

39. How do you use allMatch(), anyMatch(), and noneMatch() in Streams?

Answer:

  • allMatch(predicate): Checks if all elements in the Stream match the given predicate.
  • anyMatch(predicate): Checks if any elements in the Stream match the given predicate.
  • noneMatch(predicate): Checks if no elements in the Stream match the given predicate.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
boolean allEven = numbers.stream().allMatch(n -> n % 2 == 0);
boolean anyEven = numbers.stream().anyMatch(n -> n % 2 == 0);
boolean noneNegative = numbers.stream().noneMatch(n -> n < 0);

40. What is the purpose of findFirst() and findAny() in parallel Streams?

Answer:

In parallel Streams, findFirst() returns the first element in the Stream’s encounter order, while findAny() returns any element, not necessarily the first.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> first = numbers.parallelStream().findFirst();
Optional<Integer> any = numbers.parallelStream().findAny();

41. How do you perform sorted operations in Streams?

Answer:

You can use the sorted() method to sort elements in a Stream. You can also provide a custom Comparator if needed.

Example:

List<Integer> numbers = Arrays.asList(5, 3, 1, 4, 2);
List<Integer> sortedNumbers = numbers.stream().sorted().collect(Collectors.toList());

42. What is the purpose of distinct() in Streams?

Answer:

The distinct() operation filters out duplicate elements in a Stream, ensuring that only unique elements are included.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 3, 5);
List<Integer> distinctNumbers = numbers.stream().distinct().collect(Collectors.toList());

43. How do you use limit() and skip() in Streams?

Answer:

  • limit(n): Returns a Stream with the first n elements.
  • skip(n): Returns a Stream with the first n elements removed.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> limited = numbers.stream().limit(3).collect(Collectors.toList());
List<Integer> skipped = numbers.stream().skip(2).collect(Collectors.toList());

44. How do you handle exceptions in Streams?

Answer:

You can use the try-catch block within a map or flatMap operation to handle exceptions.

Example:

List<String> numbers = Arrays.asList("1", "2", "3", "four", "5");
List<Integer> parsedNumbers = numbers.stream()
        .map(s -> {
            try {
                return Integer.parseInt(s);
            } catch (NumberFormatException e) {
                return null; // Or handle the exception as needed
            }
        })
        .filter(Objects::nonNull)
        .collect(Collectors.toList());

45. What is the purpose of groupingBy() in Streams?

Answer:

The groupingBy() collector is used for grouping elements of a Stream based on a specified criteria.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Anna", "Alex");
Map<Character, List<String>> groupedNames = names.stream()
        .collect(Collectors.groupingBy(name -> name.charAt(0)));

46. How do you use partitioningBy() in Streams?

Answer:

The partitioningBy() collector is used for partitioning elements of a Stream into two groups based on a predicate.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Map<Boolean, List<Integer>> evenOddPartition = numbers.stream()
        .collect(Collectors.partitioningBy(n -> n % 2 == 0));

47. What is the purpose of mapping() in Streams?

Answer:

The mapping() collector allows you to apply a function to the elements of a Stream before applying further collectors.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Set<Integer> nameLengths = names.stream()
        .collect(Collectors.mapping(String::length, Collectors.toSet()));

48. How do you use joining() in Streams?

Answer:

The joining() collector concatenates the elements of a Stream into a single String.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String joinedNames = names.stream().collect(Collectors.joining(", "));

49. What is the purpose of summarizingInt() in Streams?

Answer:

The summarizingInt() collector provides summary statistics for integer-valued properties of elements in a Stream.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35)
);
IntSummaryStatistics ageStats = people.stream()
        .collect(Collectors.summarizingInt(Person::getAge));

50. How do you use collectingAndThen() in Streams?

Answer:

The collectingAndThen() collector allows you to perform a final transformation on the result of another collector.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String result = names.stream()
        .collect(Collectors.collectingAndThen(Collectors.joining(", "), s -> "Names: " + s));

51. How do you use toMap() in Streams?

Answer:

The toMap() collector is used for converting elements of a Stream into a Map.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35)
);
Map<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toMap(Person::getName, Person::getAge));

52. What is the purpose of toConcurrentMap() in Streams?

Answer:

Similar to toMap(), toConcurrentMap() creates a concurrent map instead of a regular map.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35)
);
ConcurrentMap<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toConcurrentMap(Person::getName, Person::getAge));

53. How do you use joining() with a delimiter in Streams?

Answer:

You can specify a delimiter when using the joining() collector.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String joinedNames = names.stream()
        .collect(Collectors.joining(", ", "Names: ", "."));

54. What is the purpose of averagingInt() in Streams?

Answer:

The averagingInt() collector calculates the average of integer-valued properties of elements in a Stream.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35)
);
double averageAge = people.stream()
        .collect(Collectors.averagingInt(Person::getAge));

55. How do you use summingInt() in Streams?

Answer:

The summingInt() collector calculates the sum of integer-valued properties of elements in a Stream.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35)
);
int totalAge = people.stream()
        .collect(Collectors.summingInt(Person::getAge));

56. What is the purpose of maxBy() and minBy() in Streams?

Answer:

  • maxBy(comparator): Finds the maximum element according to the provided comparator.
  • minBy(comparator): Finds the minimum element according to the provided comparator.

Example:

List<Integer> numbers = Arrays.asList(5, 3, 8, 1, 2);
Optional<Integer> max = numbers.stream().collect(Collectors.maxBy(Comparator.naturalOrder()));
Optional<Integer> min = numbers.stream().collect(Collectors.minBy(Comparator.naturalOrder()));

57. What is the purpose of collectingAndThen() in Streams?

Answer:

The collectingAndThen() collector allows you to perform a final transformation on the result of another collector.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String result = names.stream()
        .collect(Collectors.collectingAndThen(Collectors.joining(", "), s -> "Names: " + s));

58. How do you use groupingBy() with a downstream collector?

Answer:

You can use groupingBy() with a downstream collector to perform further operations on grouped elements.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
Map<Integer, Long> ageToCount = people.stream()
        .collect(Collectors.groupingBy(
                Person::getAge,
                Collectors.counting()
        ));

59. What is the purpose of mapping() in combination with other collectors?

Answer:

mapping() is often used in combination with other collectors to transform elements before applying further operations.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Set<Integer> nameLengths = names.stream()
        .collect(Collectors.mapping(String::length, Collectors.toSet()));

60. How do you use reducing() in Streams?

Answer:

The reducing() collector allows you to perform a reduction operation on the elements of a Stream.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> sum = numbers.stream()
        .collect(Collectors.reducing((a, b) -> a + b));

61. What is the purpose of toSet() and toList() in Streams?

Answer:

  • toSet(): Collects elements into a Set.
  • toList(): Collects elements into a List.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Set<String> nameSet = names.stream().collect(Collectors.toSet());
List<String> nameList = names.stream().collect(Collectors.toList());

62. How do you use joining() to concatenate elements into a single String?

Answer:

The joining() collector concatenates elements into a single String.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String joinedNames = names.stream().collect(Collectors.joining(", "));

63. What is the purpose of flatMapping() in Streams?

Answer:

flatMapping() is used when you need to apply a mapper function that returns a Stream and then flatten the resulting Streams into a single Stream.

Example:

List<List<Integer>> nestedLists = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4, 5));
List<Integer> flatList = nestedLists.stream()
        .collect(Collectors.flatMapping(List::stream, Collectors.toList()));

64. How do you use toCollection() in Streams?

Answer:

The toCollection() collector allows you to specify the type of collection to store the elements.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
LinkedList<String> nameLinkedList = names.stream()
        .collect(Collectors.toCollection(LinkedList::new));

65. How do you use partitioningBy() in Streams?

Answer:

partitioningBy() is used for partitioning elements of a Stream into two groups based on a predicate.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
Map<Boolean, List<Person>> partitioned = people.stream()
        .collect(Collectors.partitioningBy(p -> p.getAge() > 30));

66. What is the purpose of teeing() in Streams?

Answer:

teeing() combines the results of two collectors into one using a merging function.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double averageAndSum = numbers.stream()
        .collect(Collectors.teeing(
                Collectors.averagingInt(n -> n),
                Collectors.summingInt(n -> n),
                (average, sum) -> average + sum
        ));

67. How do you use filtering() in Streams?

Answer:

filtering() is used to filter elements based on a predicate after another collector has been applied.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
        .collect(Collectors.filtering(n -> n % 2 == 0, Collectors.toList()));

68. What is the purpose of joining() with no arguments?

Answer:

When called with no arguments, joining() concatenates elements into a single String with no delimiter.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String joinedNames = names.stream().collect(Collectors.joining());

69. How do you use groupingByConcurrent() in Streams?

Answer:

groupingByConcurrent() is similar to groupingBy(), but creates a concurrent map.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<Integer, List<Person>> ageToPeople = people.stream()
        .collect(Collectors.groupingByConcurrent(Person::getAge));

70. What is the purpose of toUnmodifiableList() in Streams?

Answer:

toUnmodifiableList() creates an unmodifiable List.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> unmodifiableNames = names.stream()
        .collect(Collectors.toUnmodifiableList());

71. How do you use groupingByConcurrent() with a downstream collector?

Answer:

groupingByConcurrent() can be used with a downstream collector to perform further operations on grouped elements, while maintaining concurrency.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<Integer, Long> ageToCount = people.stream()
        .collect(Collectors.groupingByConcurrent(
                Person::getAge,
                Collectors.counting()
        ));

72. What is the purpose of groupingByConcurrent() with a Supplier?

Answer:

groupingByConcurrent() with a Supplier allows you to specify a custom concurrent map implementation.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<Integer, List<Person>> ageToPeople = people.stream()
        .collect(Collectors.groupingByConcurrent(
                Person::getAge,
                ConcurrentHashMap::new,
                Collectors.toList()
        ));

73. How do you use toConcurrentMap() in Streams?

Answer:

toConcurrentMap() collects elements into a concurrent map.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toConcurrentMap(
                Person::getName,
                Person::getAge
        ));

74. What is the purpose of toConcurrentMap() with merge function?

Answer:

toConcurrentMap() with a merge function is used to handle duplicate keys.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toConcurrentMap(
                Person::getName,
                Person::getAge,
                (existing, replacement) -> existing
        ));

75. How do you use toConcurrentMap() with Supplier and merge function?

Answer:

toConcurrentMap() with a Supplier and merge function allows you to specify a custom concurrent map implementation and handle duplicate keys.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Charlie", 35),
        new Person("Anna", 30)
);
ConcurrentMap<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toConcurrentMap(
                Person::getName,
                Person::getAge,
                (existing, replacement) -> existing,
                ConcurrentHashMap::new
        ));

76. How do you use mapping() in Streams?

Answer:

mapping() is used to perform an additional transformation on the elements after another collector has been applied.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
Set<Integer> nameLengths = names.stream()
        .collect(Collectors.mapping(String::length, Collectors.toSet()));

77. What is the purpose of flatMapping() in Streams?

Answer:

flatMapping() is used to flatten nested streams that result from applying a mapping function.

Example:

List<List<Integer>> nestedList = Arrays.asList(
        Arrays.asList(1, 2),
        Arrays.asList(3, 4),
        Arrays.asList(5, 6)
);
List<Integer> flattenedList = nestedList.stream()
        .flatMap(Collection::stream)
        .collect(Collectors.toList());

78. How do you use toMap() with merge function in Streams?

Answer:

toMap() with a merge function is used to handle duplicate keys by specifying how to resolve conflicts.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Anna", 30)
);
Map<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toMap(
                Person::getName,
                Person::getAge,
                (existing, replacement) -> existing
        ));

79. What is the purpose of toMap() with Supplier and merge function in Streams?

Answer:

toMap() with a Supplier and merge function allows you to specify a custom map implementation and handle duplicate keys.

Example:

List<Person> people = Arrays.asList(
        new Person("Alice", 30),
        new Person("Bob", 25),
        new Person("Anna", 30)
);
Map<String, Integer> nameToAge = people.stream()
        .collect(Collectors.toMap(
                Person::getName,
                Person::getAge,
                (existing, replacement) -> existing,
                LinkedHashMap::new
        ));

80. How do you use toSet() in Streams?

Answer:

toSet() is used to collect elements into a Set, removing duplicates.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 2, 4, 5, 3);
Set<Integer> uniqueNumbers = numbers.stream()
        .collect(Collectors.toSet());

81. How do you use joining() in Streams?

Answer:

joining() is used to concatenate the elements of a CharSequence.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String concatenatedNames = names.stream()
        .collect(Collectors.joining(", "));

82. What is the purpose of joining() with a delimiter and prefix/suffix in Streams?

Answer:

joining() with a delimiter and optional prefix/suffix allows you to customize the format of the concatenated result.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String formattedNames = names.stream()
        .collect(Collectors.joining(", ", "Names: [", "]"));

83. How do you use teeing() in Streams?

Answer:

teeing() is used to apply two collectors in parallel and combine their results using a function.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double averageAndSum = numbers.stream()
        .collect(Collectors.teeing(
                Collectors.averagingInt(n -> n),
                Collectors.summingInt(n -> n),
                (average, sum) -> average + sum
        ));

84. What is the purpose of teeing() with a merger in Streams?

Answer:

teeing() with a merger is used when the final result requires a combination of both intermediate results.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
int result = numbers.stream()
        .collect(Collectors.teeing(
                Collectors.summingInt(n -> n),
                Collectors.counting(),
                (sum, count) -> sum / count
        ));

85. How do you use filtering() in Streams?

Answer:

filtering() is used to apply a filter condition on elements before performing further operations.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
List<Integer> evenNumbers = numbers.stream()
        .collect(Collectors.filtering(n -> n % 2 == 0, Collectors.toList()));

86. How do you use partitioningBy() in Streams?

Answer:

partitioningBy() is used to split elements into two groups based on a predicate.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Map<Boolean, List<Integer>> evenAndOdd = numbers.stream()
        .collect(Collectors.partitioningBy(n -> n % 2 == 0));

87. What is the purpose of partitioningBy() with downstream collector in Streams?

Answer:

partitioningBy() with a downstream collector allows you to perform additional operations on the elements in each partition.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
Map<Boolean, Integer> sumOfEvenAndOdd = numbers.stream()
        .collect(Collectors.partitioningBy(n -> n % 2 == 0, Collectors.summingInt(n -> n)));

88. How do you use groupingBy() in Streams?

Answer:

groupingBy() is used to categorize elements into different groups based on a classifier function.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
Map<Character, List<String>> groupedNames = names.stream()
        .collect(Collectors.groupingBy(s -> s.charAt(0)));

89. What is the purpose of groupingBy() with downstream collector in Streams?

Answer:

groupingBy() with a downstream collector allows you to perform additional operations on the elements within each group.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
Map<Character, Integer> totalLengthOfNames = names.stream()
        .collect(Collectors.groupingBy(s -> s.charAt(0), Collectors.summingInt(String::length)));

90. How do you use groupingBy() with treeMap in Streams?

Answer:

groupingBy() with treeMap allows you to maintain the order of elements within each group.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
Map<Character, List<String>> groupedNames = names.stream()
        .collect(Collectors.groupingBy(s -> s.charAt(0), TreeMap::new, Collectors.toList()));

91. How do you use flatMapping() in Streams?

Answer:

flatMapping() is used to transform elements and flatten the results into a single stream.

Example:

List<List<Integer>> nestedNumbers = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4, 5), Arrays.asList(6));
List<Integer> flattenedNumbers = nestedNumbers.stream()
        .collect(Collectors.flatMapping(List::stream, Collectors.toList()));

92. What is the purpose of mapping() in Streams?

Answer:

mapping() is used to apply a function to elements before applying further collectors.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<Character> firstCharacters = names.stream()
        .collect(Collectors.mapping(s -> s.charAt(0), Collectors.toList()));

93. How do you use toMap() with a merging function in Streams?

Answer:

toMap() with a merging function is used to handle situations where duplicate keys are encountered.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
Map<Character, String> nameMap = names.stream()
        .collect(Collectors.toMap(s -> s.charAt(0), Function.identity(), (existing, replacement) -> existing));

94. What is the purpose of toMap() with supplier, accumulator, and combiner in Streams?

Answer:

toMap() with these parameters allows you to have fine-grained control over the map creation process.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
Map<Character, String> nameMap = names.stream()
        .collect(Collectors.toMap(s -> s.charAt(0), Function.identity(), (existing, replacement) -> existing, LinkedHashMap::new));

95. How do you use toConcurrentMap() in Streams?

Answer:

toConcurrentMap() is used to create a concurrent map.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
ConcurrentMap<Character, String> concurrentNameMap = names.stream()
        .collect(Collectors.toConcurrentMap(s -> s.charAt(0), Function.identity()));

96. How do you use joining() in Streams?

Answer:

joining() is used to concatenate elements into a single string.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
String concatenatedNames = names.stream()
        .collect(Collectors.joining(", "));

97. What is the purpose of teeing() in Streams?

Answer:

teeing() allows you to apply two collectors to the same stream and combine their results.

Example:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);
double average = numbers.stream()
        .collect(Collectors.teeing(
                Collectors.summingDouble(n -> n),
                Collectors.counting(),
                (sum, count) -> sum / count));

98. How do you use groupingByConcurrent() in Streams?

Answer:

groupingByConcurrent() is similar to groupingBy(), but it creates a concurrent map.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
ConcurrentMap<Character, List<String>> groupedNames = names.stream()
        .collect(Collectors.groupingByConcurrent(s -> s.charAt(0)));

99. What is the purpose of collectingAndThen() in Streams?

Answer:

collectingAndThen() is used to apply a final transformation after the main collector.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie", "Amy", "Bill");
String concatenatedNames = names.stream()
        .collect(Collectors.collectingAndThen(Collectors.joining(", "), result -> "Names: " + result));

100. How do you use toUnmodifiableList() in Streams?

Answer:

toUnmodifiableList() creates an unmodifiable list as the result of a collector.

Example:

List<String> names = Arrays.asList("Alice", "Bob", "Charlie");
List<String> unmodifiableNames = names.stream()
        .collect(Collectors.toUnmodifiableList());