SoFunction
Updated on 2025-05-13

A super detailed tutorial on comparing map and flatMap in Java Stream

1. Comparison of core differences

method Input Type Output Type Applicable scenarios Convert relationship
map() Function<T,R> Stream<R> One-to-one conversion of elements 1:1
flatMap() Function<T,Stream<R>> Stream<R> One-to-many conversion and merge of elements 1:N

2. Detailed explanation of map() method

1. Basic functions

Convert each element in the stream to another object

2. Typical application scenarios

  • Type conversion
  • Extract object properties
  • Numerical calculation

3. Sample code

import ;
import ;
import ;

public class MapExample {
    public static void main(String[] args) {
        // Example 1: String to uppercase        List&lt;String&gt; words = ("hello", "world");
        List&lt;String&gt; upperCaseWords = ()
                .map(String::toUpperCase)
                .collect(());
        (upperCaseWords); // [HELLO, WORLD]

        // Example 2: Extract object properties        class User {
            String name;
            User(String name) {  = name; }
            String getName() { return name; }
        }
        
        List&lt;User&gt; users = (
            new User("Alice"),
            new User("Bob")
        );
        
        List&lt;String&gt; names = ()
                .map(User::getName)
                .collect(());
        (names); // [Alice, Bob]
    }
}

3. Detailed explanation of flatMap() method

1. Basic functions

Convert each element to a stream and then merge all streams into one stream

2. Typical application scenarios

  • Handle nested collections
  • Split string into multiple elements
  • Merge multiple streams

3. Sample code

import ;
import ;
import ;

public class FlatMapExample {
    public static void main(String[] args) {
        // Example 1: Expand nested collection        List&lt;List&lt;String&gt;&gt; nestedList = (
            ("Java", "Python"),
            ("C++", "Go"),
            ("JavaScript", "TypeScript")
        );
        
        List&lt;String&gt; languages = ()
                .flatMap(List::stream)
                .collect(());
        (languages); 
        // [Java, Python, C++, Go, JavaScript, TypeScript]

        // Example 2: Split string into word        List&lt;String&gt; sentences = (
            "Hello World",
            "Java Stream API"
        );
        
        List&lt;String&gt; words = ()
                .flatMap(sentence -&gt; ((" ")))
                .collect(());
        (words); 
        // [Hello, World, Java, Stream, API]
    }
}

4. Comparison of use cases

Scenario: Data processing for students’ course selection

import .*;
import .*;

class Student {
    String name;
    List&lt;String&gt; courses;
    
    Student(String name, List&lt;String&gt; courses) {
         = name;
         = courses;
    }
    
    List&lt;String&gt; getCourses() { return courses; }
}

public class CompareExample {
    public static void main(String[] args) {
        List&lt;Student&gt; students = (
            new Student("Alice", ("Math", "Physics")),
            new Student("Bob", ("History", "Art"))
        );

        // Error usage: map handles nested collections        List&lt;List&lt;String&gt;&gt; wrongResult = ()
                .map(Student::getCourses)
                .collect(());
        ("Error result:" + wrongResult); 
        // [[Math, Physics], [History, Art]]

        // Correct usage: flatMap expands nested collection        List&lt;String&gt; correctResult = ()
                .flatMap(student -&gt; ().stream())
                .collect(());
        ("Correct result:" + correctResult); 
        // [Math, Physics, History, Art]

        // Comprehensive application: count all courses        long courseCount = ()
                .flatMap(student -&gt; ().stream())
                .count();
        ("Total Courses:" + courseCount); // 4
    }
}

5. Frequently Asked Questions

Q1: When should flatMap be used?

When the following structure needs to be handled:

  • List<List<T>> → List<T>
  • Stream<Stream<R>> → Stream<R>
  • When you need to split an element into multiple child elements

Q2: Can map and flatMap be used in combination?

Yes, common combinations:

()
    .map(...)    // Initial conversion    .flatMap(...) // Expand processing    .collect(...)

Q3: How to deal with multi-layer nesting?

Use flatMap multiple times:

List&lt;List&lt;List&lt;String&gt;&gt;&gt; deepNested = ...;
()
    .flatMap(List::stream)  // Expand the first layer    .flatMap(List::stream)  // Expand the second layer    .collect(...);

6. Summary and comparison

operate Input elements Number of output elements Final result structure
map Single element 1 new element Maintain the original flow structure
flatMap Single element 0-N new elements Merge into a single-class structure

Selection Principles

  • Need to simply convert a single element → Usemap()
  • Need to expand nested structure/generate multiple elements → UseflatMap()

The above code can be copied directly to Java 8+ environment to run. It is recommended to actually test and observe the output results in the IDE to deepen your understanding.

This is the end of this article about comparing map and flatMap in Java Stream. For more information about comparing Java map and flatMap, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!