Java
programming
algorithm
find smallest number
code optimization

Most efficient way to find smallest of 3 numbers Java?

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

Introduction

Finding the smallest of three numbers is a constant-time problem, so the practical question is not whether one solution is dramatically faster. The real question is which solution is correct, readable, and appropriate for the data type.

In normal Java code, the best answers are usually either Math.min or a simple comparison chain. The performance difference between them is negligible in real applications.

The Shortest Readable Answer

For primitive numeric values, Math.min is usually the cleanest choice:

java
1public class SmallestOfThree {
2    public static int smallest(int a, int b, int c) {
3        return Math.min(a, Math.min(b, c));
4    }
5
6    public static void main(String[] args) {
7        System.out.println(smallest(14, 7, 9));
8        System.out.println(smallest(-5, -2, 3));
9    }
10}

The inner Math.min finds the smaller of b and c, and the outer call compares that result with a.

This is concise, correct, and easy to maintain.

Explicit Comparison Chain

If you want every comparison to be spelled out, a direct if chain is equally valid:

java
1public class SmallestOfThree {
2    public static int smallest(int a, int b, int c) {
3        if (a <= b && a <= c) {
4            return a;
5        }
6        if (b <= a && b <= c) {
7            return b;
8        }
9        return c;
10    }
11}

This version can be useful in interviews or teaching because the control flow is completely explicit.

Efficiency In Context

Both versions run in O(1) time and use O(1) space. The job is only a few comparisons, so there is no meaningful algorithmic optimization to chase.

That means clarity should dominate the decision. If the code becomes more complicated in the name of speed, the tradeoff is usually not worth it.

What To Avoid For Exactly Three Values

Developers sometimes reach for arrays, streams, or more abstract patterns for a fixed three-value comparison. For example:

java
1import java.util.Arrays;
2
3public class SmallestWithStream {
4    public static int smallest(int a, int b, int c) {
5        return Arrays.stream(new int[] {a, b, c}).min().orElseThrow();
6    }
7}

This works, but it allocates an array and sets up a stream pipeline for a problem that only needs a couple of direct comparisons. It is harder to justify unless the values already exist inside a collection.

When The Problem Is More General

Sometimes the real requirement is not three primitive numbers but three objects such as dates, prices, or custom domain types. In that case, a comparator-based helper is the clean generalization:

java
1import java.util.Comparator;
2
3public class SmallestGeneric {
4    public static <T> T smallest(T a, T b, T c, Comparator<T> comparator) {
5        T min = comparator.compare(a, b) <= 0 ? a : b;
6        return comparator.compare(min, c) <= 0 ? min : c;
7    }
8}

That solves a different problem well. The key is not to over-generalize before the requirement actually changes.

Common Pitfalls

The biggest mistake is treating this as a serious optimization problem. For three numbers, the standard constant-time solutions are already effectively optimal.

Another pitfall is forgetting equality cases. If two values tie for the smallest value, the code should still return one of them correctly. Using <= in explicit comparisons makes that behavior clear.

A third issue is adding abstraction too early. If the requirement is exactly three primitive numbers, Math.min or a direct comparison chain is the right level of complexity.

Summary

  • For three primitive numbers, Math.min(a, Math.min(b, c)) is usually the best balance of brevity and clarity.
  • A direct if chain is equally efficient and sometimes easier to explain.
  • Both common solutions are constant-time and effectively identical for real-world performance.
  • Streams or arrays are unnecessary overhead when the input is exactly three values.
  • Use a comparator-based helper only when the problem expands beyond primitive numeric types.

Related reading
Course
Intermediate
27 lessons
15 hours
DSA Fundamentals

Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Data Structures & Algorithms practice on Codemia

Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.

Practice algorithms

All Rights Reserved.