← Back to list

Java Streams In-Depth : Part-1

In this artice, we will discuss in detail about Java Stream basics, filter, map and reduce operations.

Chanchal Mishra · 2026-02-22 17:43 · 3 claps · 1.9 min read
#core-java #core-java-interview #java8-streams #java8 #java-interview-questions
Open on Medium ↗

Java Streams In-Depth : Part-1

In this artice, we will discuss in detail about Java Stream basics, filter, map and reduce operations.

The motivation for streams came from competitive pressure and developer envy.

  • Google’s FlumeJava: Internal bulk data processing system.
  • Microsoft’s LINQ/PLINQ: Extremely popular among .NET developers.
  • Developer Demand: Java developers wanted similar functional capabilities.
  • Business Benefits: Single-threaded applications could leverage concurrency with minimal code changes.

The Problem with Traditional Java Collections:-

// Traditional approach - verbose and error-prone
List<String> result = new ArrayList<>();
for (Employee emp : employees) {
    if (emp.getDepartment().equals("Engineering") && emp.getSalary() > 70000) {
        result.add(emp.getName().toUpperCase());
    }
}
Collections.sort(result);

Core Architecture: Stream Processing PipelineThe Three-Stage Pipeline:-

  1. Source Stage: Collections provide data stream.
  2. Intermediate Operations: Transform data (lazy evaluation).
  3. Terminal Operations: Produce final results (trigger execution).
List<String> result = employees.stream()           // Source
    .filter(emp -> emp.getSalary() > 70000)        // Intermediate
    .map(Employee::getName)                        // Intermediate  
    .map(String::toUpperCase)                      // Intermediate
    .sorted()                                      // Intermediate
    .collect(Collectors.toList());                 // Terminal

Filter Operations — Selective Processing

Purpose: Select elements based on boolean predicates.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);

// Basic filtering
List<Integer> evenNumbers = numbers.stream()
    .filter(n -> n % 2 == 0)
    .collect(Collectors.toList());
// Result: [2, 4, 6, 8, 10]

// Multiple filter conditions
List<Integer> filtered = numbers.stream()
    .filter(n -> n > 3)              // Greater than 3
    .filter(n -> n % 2 == 0)         // Even numbers
    .collect(Collectors.toList());
// Result: [4, 6, 8, 10]

// Complex business filtering
List<Employee> seniorEngineers = employees.stream()
    .filter(emp -> "Engineering".equals(emp.getDepartment()))
    .filter(emp -> emp.getAge() > 30)
    .filter(emp -> emp.getSalary() > 80000)
    .collect(Collectors.toList());

Performance Characteristics:

  • Time Complexity: O(n) — each element evaluated once.
  • Space Complexity: O(1) for filtering predicate.
  • Parallel Benefits: Excellent — independent element evaluation.

Map Operations — Data Transformation

Purpose: Transform each element to a different value or type.

// Simple transformations
List<String> upperCaseNames = employees.stream()
    .map(Employee::getName)
    .map(String::toUpperCase)
    .collect(Collectors.toList());

// Type transformation
List<Integer> nameLengths = employees.stream()
    .map(Employee::getName)
    .map(String::length)
    .collect(Collectors.toList());

// Complex business transformation
List<EmployeeSummary> summaries = employees.stream()
    .map(emp -> new EmployeeSummary(
        emp.getName(),
        emp.getDepartment(),
        calculateTotalCompensation(emp),
        determineLevel(emp.getAge(), emp.getSalary())
    ))
    .collect(Collectors.toList());

// Specialized numeric mappings
IntSummaryStatistics salaryStats = employees.stream()
    .mapToInt(emp -> (int) emp.getSalary())  // Avoid boxing
    .summaryStatistics();

System.out.println("Average salary: " + salaryStats.getAverage());
System.out.println("Max salary: " + salaryStats.getMax());

Reduce Operations — Data Aggregation

Purpose: Combine stream elements into a single result.

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5);

// Basic reduction
Optional<Integer> sum = numbers.stream()
    .reduce(Integer::sum);
// Result: Optional

// Reduction with identity value
Integer sumWithIdentity = numbers.stream()
    .reduce(0, Integer::sum);
// Result: 15 (never Optional)

// Complex business reduction
double totalSalary = employees.stream()
    .map(Employee::getSalary)
    .reduce(0.0, Double::sum);

// String concatenation with reduce
String allNames = employees.stream()
    .map(Employee::getName)
    .reduce("Employees: ", (acc, name) -> acc + name + " ");

// Custom accumulator and combiner for parallel processing
String departmentSummary = employees.parallelStream()
    .reduce("",
        (partial, emp) -> partial + emp.getName() + "(" + emp.getDepartment() + ") ",
        String::concat  // Combiner for parallel streams
    );

Specialised Reductions:

// Built-in terminal operations are optimized reductions
long count = employees.stream().count();

OptionalDouble average = employees.stream()
        .mapToDouble(Employee::getSalary)
        .average();

Optional<Employee> maxSalary = employees.stream()
        .max(Comparator.comparing(Employee::getSalary));

boolean anyHighEarners = employees.stream()
        .anyMatch(emp -> emp.getSalary() > 100000);

메타데이터
post_id
faa95b48a062
slug
java-streams-in-depth-part-1-faa95b48a062
url
https://medium.com/@mishra-ck/java-streams-in-depth-part-1-faa95b48a062
canonical_url
https://medium.com/@mishra-ck/java-streams-in-depth-part-1-faa95b48a062
author_url
https://medium.com/@mishra-ck
status
ok
fetched_at
2026-07-30 03:42:02