Find Max and Min Using Streams

Java coding interview problem for Java 8 Streams: Find Max and Min Using Streams.

Finding maximum and minimum values is one of the most common Java coding interview problems.

Examples:

  • Find the largest number in a list.
  • Find the smallest number in a list.
  • Find highest salary employee.
  • Find lowest priced product.

This problem introduces:

  • Stream API
  • max()
  • min()
  • Comparator
  • Optional
  • Reduction operations

What are Maximum and Minimum Problems?

Maximum and minimum problems find the extreme values from a collection.


Example:

Input:

[10,50,20,90,30]

Maximum:

90

Minimum:

10

Understanding Aggregation Operations

Aggregation means combining multiple values into a single result.

Examples:

List Numbers

      ↓

Calculate

      ↓

Single Value

Common aggregation operations:

Operation Result
sum() Total value
max() Largest value
min() Smallest value
count() Number of elements
average() Average value

Why Max and Min Problems Are Important?

These problems test:

1. Stream API Knowledge

Understanding:

stream()
max()
min()

2. Comparator Usage

Finding maximum based on:

  • Salary
  • Age
  • Price
  • Date

3. Optional Handling

Streams return:

Optional<T>

because collections can be empty.


Real-World Applications

Banking Systems

Find:

Highest transaction amount

Lowest transaction amount

Employee Management

Find:

Highest paid employee

Lowest paid employee

E-Commerce

Find:

Most expensive product

Cheapest product

Monitoring Systems

Find:

Maximum response time

Minimum response time

Problem Statement

Given a list of integers, find:

  1. Maximum number
  2. Minimum number

using Java Streams.


Example 1

Input:

[10,20,5,40,30]

Output:

Maximum = 40

Minimum = 5

Example 2

Input:

[100,50,200,25]

Output:

Maximum = 200

Minimum = 25

Java Stream API Overview

Streams provide a functional approach for processing collections.


Stream flow:

Collection

    ↓

Stream

    ↓

Intermediate Operations

    ↓

Terminal Operation

    ↓

Result

Example:

numbers.stream()
       .max();

Stream Pipeline Concept

Example:

numbers.stream()

.max(
    Comparator.naturalOrder()
);

Flow:

List<Integer>

      ↓

stream()

      ↓

Compare Elements

      ↓

Find Maximum

      ↓

Optional<Integer>

Approach 1 — Traditional Loop Approach

Before Streams, loops were commonly used.


Algorithm

  1. Initialize max value.
  2. Traverse list.
  3. Compare every element.
  4. Update maximum.

Java Program — Find Maximum

import java.util.*;

public class FindMaximum {


    public static int findMax(
            List<Integer> numbers) {


        int max = numbers.get(0);


        for(Integer number : numbers) {


            if(number > max) {

                max = number;

            }

        }


        return max;

    }


    public static void main(String[] args) {


        List<Integer> numbers =
                Arrays.asList(
                    10,
                    20,
                    5,
                    40,
                    30
                );


        System.out.println(
            findMax(numbers)
        );

    }

}

Output

40

Dry Run — Maximum

Input:

[10,20,5,40,30]

Initial:

max = 10

Compare:

20 > 10

Update:

max = 20

Compare:

5 > 20

No change.


Compare:

40 > 20

Update:

max = 40

Compare:

30 > 40

No change.


Final:

max = 40

Java Program — Find Minimum

public static int findMin(
        List<Integer> numbers) {


    int min = numbers.get(0);


    for(Integer number : numbers) {


        if(number < min) {

            min = number;

        }

    }


    return min;

}

Complexity Analysis — Loop Approach

Let:

n = number of elements

Traversal:

O(n)

Space:

O(1)

Approach 2 — Using Stream max()

Java Stream provides:

max()

to find maximum element.


Syntax:

stream.max(comparator)

Example:

Optional<Integer> max =

numbers.stream()

.max(
    Comparator.naturalOrder()
);

Java Program — Maximum Using Streams

import java.util.*;

public class MaximumUsingStreams {


    public static Integer findMax(
            List<Integer> numbers) {


        return numbers.stream()

                .max(
                    Comparator.naturalOrder()
                )

                .orElse(null);

    }


    public static void main(String[] args) {


        List<Integer> numbers =
                Arrays.asList(
                    10,
                    20,
                    5,
                    40,
                    30
                );


        System.out.println(
            findMax(numbers)
        );

    }

}

Output

40

Understanding Comparator.naturalOrder()

Natural ordering means:

Ascending order

Example:

Numbers:

10,20,5,40

Comparison:

40 is greater

For maximum:

Comparator.naturalOrder()

is used.


For minimum:

Comparator.reverseOrder()

or:

min()

can be used.


Java Program — Minimum Using Streams

public static Integer findMin(
        List<Integer> numbers) {


    return numbers.stream()

            .min(
                Comparator.naturalOrder()
            )

            .orElse(null);

}

Output

5

Stream Pipeline Explanation

Input:

10,20,5,40,30

Stream:

10

20

5

40

30

max():

Compare:

10 vs 20

20 vs 5

20 vs 40

40 vs 30

Result:

40

Using Primitive Streams

For numbers, Java provides:

IntStream

LongStream

DoubleStream

Example:

int max =

numbers.stream()

.mapToInt(
    Integer::intValue
)

.max()

.orElse(0);

Advantages:

  • No boxing/unboxing
  • Better performance
  • Built for primitive values

Finding Maximum With reduce()

Another Stream approach:

Optional<Integer> max =

numbers.stream()

.reduce(
    Integer::max
);

How it works:

10,20,5,40,30

↓

20

↓

20

↓

40

↓

40

Result:

40

Handling Empty Collections

Important interview scenario.

Input:

[]

Problem:

No maximum exists.


Stream returns:

Optional<Integer>

Example:

Optional<Integer> result =

numbers.stream()

.max(
    Comparator.naturalOrder()
);

Check:

result.isPresent()

Or:

.orElse(0)

Handling Null Values

Input:

[10,20,null,40]

Problem:

Comparator cannot compare null.


Solution:

Filter null values.

numbers.stream()

.filter(
    Objects::nonNull
)

.max(
    Comparator.naturalOrder()
);

Finding Highest Salary Employee

Common enterprise example.

Employee:

John     90000

Alice   150000

Bob     70000

Requirement:

Find:

Highest Salary Employee

Code:

Employee highest =

employees.stream()

.max(

Comparator.comparing(
    Employee::getSalary
)

)

.orElse(null);

Finding Lowest Salary Employee

Employee lowest =

employees.stream()

.min(

Comparator.comparing(
    Employee::getSalary
)

)

.orElse(null);

Deep Dive Into Stream max() and min()

Java Stream API provides:

max()

and

min()

for finding extreme values from a stream.


max() Method

Syntax:

Optional<T> max(
    Comparator<? super T> comparator
)

Purpose:

Returns:

Largest element

based on the provided comparator.


Example:

Optional<Integer> result =

numbers.stream()

.max(
    Comparator.naturalOrder()
);

Input:

[10,50,20,90]

Output:

90

min() Method

Syntax:

Optional<T> min(
    Comparator<? super T> comparator
)

Purpose:

Returns:

Smallest element

Example:

Optional<Integer> result =

numbers.stream()

.min(
    Comparator.naturalOrder()
);

Input:

[10,50,20,90]

Output:

10

Understanding Optional Return Type

Why does Stream return:

Optional<T>

instead of:

T

?


Because the stream may contain no elements.

Example:

List<Integer> numbers =
        new ArrayList<>();

Question:

What is maximum?

Answer:

No value exists

Therefore:

Optional

safely represents:

Value exists

or

No value

Optional Handling Examples

Using orElse()

Integer max =

numbers.stream()

.max(
    Comparator.naturalOrder()
)

.orElse(0);

If empty:

Returns 0

Using ifPresent()

numbers.stream()

.max(
    Comparator.naturalOrder()
)

.ifPresent(
    value ->
    System.out.println(value)
);

Using orElseThrow()

Integer max =

numbers.stream()

.max(
    Comparator.naturalOrder()
)

.orElseThrow();

Comparator.comparing() Usage

For objects, Java cannot directly compare.

Example:

Employee:

name

salary

Need:

Compare salary field

Use:

Comparator.comparing()

Employee Example

class Employee {


    private String name;

    private double salary;


    public Employee(
            String name,
            double salary) {

        this.name = name;

        this.salary = salary;

    }


    public String getName(){

        return name;

    }


    public double getSalary(){

        return salary;

    }


    public String toString(){

        return name;

    }

}

Find Highest Salary Employee

Employee highest =

employees.stream()

.max(

Comparator.comparing(
    Employee::getSalary
)

)

.orElse(null);

Input:

John    90000

Alice  150000

Bob     70000

Comparison:

90000

vs

150000

vs

70000

Result:

Alice

Find Lowest Salary Employee

Employee lowest =

employees.stream()

.min(

Comparator.comparing(
    Employee::getSalary
)

)

.orElse(null);

Result:

Bob

Finding Second Highest Value

Common interview problem:

Input:

[10,50,20,90,30]

Expected:

50

Approach:

Sort Descending

↓

Skip First

↓

Get Next

Java:

Integer secondHighest =

numbers.stream()

.distinct()

.sorted(
    Comparator.reverseOrder()
)

.skip(1)

.findFirst()

.orElse(null);

Finding Second Lowest Value

Integer secondLowest =

numbers.stream()

.distinct()

.sorted()

.skip(1)

.findFirst()

.orElse(null);

Finding Max/Min With Multiple Fields

Sometimes one field is not enough.

Example:

Sort employees by:

  1. Salary
  2. Name

Comparator:

Comparator<Employee> comparator =

Comparator
.comparing(
    Employee::getSalary
)

.thenComparing(
    Employee::getName
);

Find maximum:

Employee employee =

employees.stream()

.max(comparator)

.orElse(null);

Finding Max Date

Example:

Orders:

Order Date

Find latest order:

Order latestOrder =

orders.stream()

.max(

Comparator.comparing(
    Order::getCreatedDate
)

)

.orElse(null);

Finding Minimum Price Product

Product:

Laptop 1200

Phone 800

Tablet 500

Code:

Product cheapest =

products.stream()

.min(

Comparator.comparing(
    Product::getPrice
)

)

.orElse(null);

Result:

Tablet

Using reduce() for Maximum

Streams support reduction operations.


Example:

Optional<Integer> max =

numbers.stream()

.reduce(
    Integer::max
);

Internal working:

10,50

↓

50


50,20

↓

50


50,90

↓

90

Result:

90

max() vs reduce()

Feature max() reduce()
Purpose Find extreme value General aggregation
Readability Better More flexible
Performance Optimized Depends on operation
Interview usage Preferred Advanced cases

Primitive Streams

Java provides specialized streams:

IntStream

LongStream

DoubleStream

Benefits:

  • No boxing
  • Better performance
  • Built-in operations

Example — IntStream max()

int max =

numbers.stream()

.mapToInt(
    Integer::intValue
)

.max()

.orElse(0);

Example — Average

double average =

numbers.stream()

.mapToInt(
    Integer::intValue
)

.average()

.orElse(0);

max() vs sorted()

Both can find maximum.


sorted()

numbers.stream()

.sorted(
    Comparator.reverseOrder()
)

.findFirst();

It performs:

Complete Sorting

Complexity:

O(n log n)

max()

numbers.stream()

.max(
    Comparator.naturalOrder()
);

Only finds:

Single maximum

Complexity:

O(n)

Comparison Table

Approach Time Complexity Best Use
max() O(n) Single maximum
min() O(n) Single minimum
sorted() O(n log n) Ranking problems
PriorityQueue O(n log k) Top K problems

Stream vs Loop Comparison

Feature Loop max()/min()
Code More Compact
Readability Good Excellent
Performance O(n) O(n)
Functional style No Yes
Object handling Manual Comparator

Comparator Internal Working

Comparator defines:

How two objects are compared

Example:

Employee::getSalary

creates comparison:

Employee A salary

vs

Employee B salary

Internally:

Object

 ↓

Extract Field

 ↓

Compare Values

 ↓

Return Result

Parallel Stream Considerations

Example:

numbers.parallelStream()

.max(
    Comparator.naturalOrder()
);

Parallel streams:

  • Split data
  • Process chunks
  • Combine results

For large datasets:

May improve performance.


For small lists:

Normal:

stream()

is usually faster.


Common Interview Mistakes

Mistake 1

Using sorted() for maximum.

Wrong:

sorted()
.findFirst()

Better:

max()

Mistake 2

Ignoring Optional.

Wrong:

.get()

without checking.


Mistake 3

Wrong comparator direction.

Example:

Comparator.reverseOrder()

with max() can produce unexpected results.


Mistake 4

Not handling null values.

Use:

.filter(
Objects::nonNull
)

Edge Cases

Case Handling
Empty list Use Optional
Single element Returns that element
Duplicate values Handled normally
Null values Filter first
Objects Use Comparator

Interview Follow-up Questions

Q1. Difference between max() and sorted()?

Q2. Why does max() return Optional?

Q3. Find highest salary employee.

Q4. Find second highest salary.

Q5. Find max by multiple fields.

Q6. How does Comparator work?

Q7. When to use primitive streams?


Related Java Collection Problems

  • Second Highest Salary Using Streams
  • Top N Highest Numbers
  • Sort Employees by Salary
  • Custom Comparator Examples
  • Find Employees With Highest Salary
  • Convert List to Map Using Streams

Key Takeaways

Maximum and minimum pattern:

Collection

      ↓

Stream

      ↓

Comparator

      ↓

max()/min()

      ↓

Optional Result

Use:

Single Maximum

max()

Use:

Single Minimum

min()

Use:

Ranking

sorted()

Use:

Large Top K Problems

PriorityQueue

Complexity:

max():

O(n)

min():

O(n)

sorted():

O(n log n)

Frequently Asked Interview Questions

Q1. Why does max() need Comparator?

Because Stream does not know how objects should be compared.


Q2. Can max() work with custom objects?

Yes, using:

Comparator.comparing()

Q3. Which is faster: max() or sorted()?

max() because it performs a single traversal.


Q4. Why use Optional?

To safely handle empty streams.


Interview Tip

When asked:

"Find maximum and minimum using Java Streams."

Explain:

  1. Use max() and min() terminal operations.
  2. Provide Comparator for custom objects.
  3. Handle Optional safely.
  4. Use primitive streams for numeric performance.
  5. Avoid sorting when only one extreme value is required.

For senior Java interviews, discuss:

  • Comparator design.
  • Optional handling.
  • Reduction operations.
  • Stream performance.
  • Parallel processing.

This demonstrates strong understanding of Java Streams, Collections, and functional programming patterns.