Monday, 7 April 2025

๐ŸŽฏ Tricky Java 8 map() vs flatMap() Questions

๐Ÿ”ฅ Q1: What's the output of this?


List<String> words = Arrays.asList("Java", "Spring"); List<String> result = words.stream() .map(word -> word.split("")) .flatMap(Arrays::stream) .distinct() .collect(Collectors.toList()); System.out.println(result);

Answer:

Output:


[J, a, v, S, p, r, i, n, g]
  • word.split("") → gives String[]

  • map() gives Stream<String[]>

  • flatMap(Arrays::stream) flattens Stream<String[]>Stream<String>

  • distinct() removes duplicates

๐Ÿ”ฅ Trick: map(Arrays::stream) would give you Stream<Stream<String>> and fail to compile in .collect().



๐Ÿ”ฅ Q2: Why does this not compile?


List<List<Integer>> list = Arrays.asList( Arrays.asList(1, 2), Arrays.asList(3, 4) ); List<Stream<Integer>> result = list.stream() .map(l -> l.stream()) .collect(Collectors.toList());

Answer:

It compiles, but the result is List<Stream<Integer>>, not List<Integer>.

To flatten the list, use:


List<Integer> result = list.stream() .flatMap(List::stream) .collect(Collectors.toList());

๐Ÿ‘‰ Trick: flatMap is needed to flatten nested streams.


๐Ÿ”ฅ Q3: How is flatMap() different from map() in Optional?


Optional<String> name = Optional.of("Java"); Optional<Optional<String>> result = name.map(n -> Optional.of(n.toUpperCase())); Optional<String> flat = name.flatMap(n -> Optional.of(n.toUpperCase()));

Answer:

  • map() → wraps result → Optional<Optional<String>>

  • flatMap() → avoids wrapping → Optional<String>

๐Ÿง  Trick: Use flatMap when the function already returns an Optional.


๐Ÿ”ฅ Q4: What happens here?


Stream<String> stream = Stream.of("apple", "banana"); stream.map(s -> s.toUpperCase()); stream.forEach(System.out::println);

Answer:

๐Ÿ’ฅ Runtime Exception: IllegalStateException: stream has already been operated upon or closed

Why? Because map() doesn’t mutate the original stream — it returns a new one. But it was never assigned.

๐Ÿง  Trick: Streams are one-time use. Always assign or chain after map() or flatMap().


๐Ÿ”ฅ Q5: Can you convert a List<String> where each string is comma-separated into a List<String> of all elements?

Answer:

Yes, with flatMap():


List<String> input = Arrays.asList("a,b,c", "d,e"); List<String> result = input.stream() .map(s -> s.split(",")) .flatMap(Arrays::stream) .collect(Collectors.toList());

Output:


[a, b, c, d, e]

๐Ÿ’ก Trick: split() gives arrays. Need flatMap(Arrays::stream) to flatten.


๐Ÿ”ฅ Q6: What’s the output?


List<String> list = Arrays.asList("a,b", "c,d", "e"); List<String[]> mapped = list.stream() .map(s -> s.split(",")) .collect(Collectors.toList()); System.out.println(mapped.size()); // ? System.out.println(mapped.get(0)[0]); // ?

Answer:

  • mapped.size() → 3

  • mapped.get(0)[0]"a"

๐Ÿง  Trick: map() does not flatten — you still have a List<String[]>, not a flat List<String>. Only flatMap() can do that.


๐Ÿ”ฅ Q7: What does this do?


Stream<String> stream = Stream.of("java", "spring"); Stream<Stream<Character>> result = stream.map(str -> str.chars().mapToObj(c -> (char) c) );

Answer:

  • It creates a Stream<Stream<Character>>

  • Each inner stream represents characters of a string

✅ If you want a flat Stream<Character>:


Stream<Character> flat = stream .flatMap(str -> str.chars().mapToObj(c -> (char) c));

๐Ÿ”ฅ Trick: Interviewers love chars + streams + mapping → always pay attention to return types.


๐Ÿ”ฅ Q8: Can you use flatMap() with primitives?

Answer:

Yes, but carefully! Primitives like IntStream, LongStream etc. don't work directly with flatMap.

Example:


List<String> list = Arrays.asList("1,2", "3,4"); List<Integer> result = list.stream() .map(s -> s.split(",")) .flatMap(Arrays::stream) .map(Integer::parseInt) .collect(Collectors.toList());

๐Ÿ”ฅ Trick: To flatMap a primitive stream, use:


.flatMapToInt(str -> str.chars()) // returns IntStream

๐Ÿ”ฅ Q9: Which is more efficient: map().flatMap() vs flatMap() directly?

Answer:

  • If you're nesting transformations (e.g. map().map()), it's fine.

  • But if you're mapping and flattening, flatMap() is better.

Bad:


.stream() .map(x -> someMethodReturningStream(x)) .map(stream -> stream.collect(Collectors.toList())) // Oops!

Better:


.stream() .flatMap(this::someMethodReturningStream)

๐Ÿ”ฅ Trick: .flatMap() avoids intermediate structures (like List of Lists) — better for performance and memory.


๐Ÿ”ฅ Q10: What if flatMap returns null?


Stream.of("hello", "world") .flatMap(s -> null) // What happens here? .collect(Collectors.toList());

Answer:

๐Ÿ’ฅ NullPointerException

❌ You cannot return null from a flatMap — it must return a valid Stream. If you want an empty result, return Stream.empty().

Correct way:


.flatMap(s -> Stream.empty())

๐Ÿ”ฅ Trick: Always return a Stream, even if it’s empty. No null allowed in flatMap().


๐Ÿงช Final Trick:

"Use map() when you transform values. Use flatMap() when you're dealing with nested structures (like lists of lists or Optionals of Optionals)."

No comments:

Post a Comment