How can I properly compare two Integers in Java?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
For primitive int values, use == and other comparison operators directly. For Integer wrapper objects, use .equals() for equality and Integer.compare() or .compareTo() for ordering. The critical rule is to never use == to compare Integer objects for value equality, because == checks reference identity, not numeric value. This distinction catches even experienced Java developers due to the Integer cache, which makes == appear to work for small values before failing on larger ones.
Comparing Primitive int Values
Primitive int comparisons are straightforward. The operators ==, !=, <, >, <=, and >= all compare numeric values directly:
No reference semantics are involved. The JVM compares the actual bit patterns on the stack. If your variables are primitive int, stay in the primitive world. It is simpler, faster, and free of null-related surprises.
Comparing Integer Wrapper Objects
When working with Integer objects (from collections, database results, JSON parsing, or method signatures that require objects), use these methods:
equals() for Value Equality
equals() compares the numeric value inside both objects. It returns false if the argument is null, so calling x.equals(null) is safe and returns false. However, calling null.equals(y) throws NullPointerException.
compareTo() for Ordering
compareTo() returns a negative integer, zero, or positive integer. It is the natural comparison method required by Comparable<Integer> and used by sorted collections like TreeSet and TreeMap.
Integer.compare() for Static Comparison
Integer.compare(int a, int b) takes primitive int parameters, avoiding autoboxing overhead. It is the preferred choice in comparator lambdas:
Why == Fails with Integer Objects
When applied to objects, == checks whether both references point to the same object in memory, not whether they hold the same numeric value:
The Integer Cache Trap
Java caches Integer objects for values between -128 and 127 (by default). When autoboxing produces a value in that range, it returns the cached instance. This makes == appear to work correctly for small values:
This is exactly why == with Integer is dangerous. Code that tests fine with small test values silently breaks when production data exceeds 127. The cache range can be extended with the JVM flag -XX:AutoBoxCacheMax=N, but relying on cache behavior for correctness is fundamentally wrong.
Complete Comparison Behavior Table
| Expression | Primitive int | Integer (cached range) | Integer (outside cache) |
a == b | Compares values | true (same object) | false (different objects) |
a.equals(b) | N/A (primitives) | true | true |
Integer.compare(a, b) | Compares values | 0 | 0 |
a.compareTo(b) | N/A (primitives) | 0 | 0 |
Objects.equals(a, b) | N/A (primitives) | true | true |
Handling Null Safely
Integer can be null, unlike primitive int. Null handling is critical when values come from database queries, API responses, or optional fields:
Objects.equals() is null-safe on both sides. Use it as the default when either argument might be null.
For ordering with potential nulls, use Comparator.nullsFirst or Comparator.nullsLast:
Unboxing: Converting Back to Primitives
If null is impossible (or has already been validated), unboxing to int simplifies comparison:
But unboxing a null reference throws NullPointerException:
A safe unboxing pattern:
Choosing the Right Comparison Method
| Scenario | Method | Why |
Two primitive int values | ==, <, > | Direct value comparison, no overhead |
Two Integer objects, no nulls | .equals() | Value equality without cache dependency |
| Either might be null | Objects.equals() | Null-safe on both sides |
| Ordering / sorting | Integer.compare() or .compareTo() | Returns negative/zero/positive |
| Sorting with nulls | Comparator.nullsFirst(Integer::compare) | Explicit null placement policy |
| Comparator lambda | Integer::compare | Avoids autoboxing, clean syntax |
Common Pitfalls
- Using == with Integer objects. This is the most common Java integer comparison bug. It compares object references, not values. The Integer cache makes it appear correct during testing with small numbers, then fail in production.
- Being fooled by the Integer cache. Values -128 to 127 share cached instances, so
==works coincidentally. Values outside this range create new objects, and==returns false even for equal values. - Calling .equals() on a potentially null reference.
null.equals(something)throwsNullPointerException. UseObjects.equals()when either side may be null. - Unboxing without null checks.
int x = nullableIntegercompiles cleanly but throws at runtime. Always validate or provide defaults before unboxing. - Mixing primitives and wrappers in conditionals. Expressions like
someInteger == 5trigger auto-unboxing ofsomeInteger, which throws if it is null. The compiler does not warn about this. - Using Integer.valueOf() expecting unique objects.
Integer.valueOf(127) == Integer.valueOf(127)is true due to caching, but this is an implementation detail, not a contract. Do not rely on it.
Summary
- Use
==and comparison operators for primitiveintvalues only. - Use
.equals()orObjects.equals()forIntegervalue equality. - Use
Integer.compare()or.compareTo()for ordering and sorting. - Never rely on
==forIntegerobjects. The Integer cache makes it appear correct for small values but fail for larger ones. - Always handle null explicitly when working with
Integer. UseObjects.equals()for null-safe equality andComparator.nullsFirst/nullsLastfor null-safe ordering. - When null is impossible, unbox to
intearly to simplify the rest of the code.
Related reading
- How can I provide different database configurations with Spring Boot?
- How can I read a large text file line by line using Java?
- How can I read all files in a folder from Java?
- How can I read an AWS S3 File with Java?
- How can I read input from the console using the Scanner class in Java?
- How can I register a secondary servlet with Spring Boot?
- How can I remove a substring from a given String?
- How can I resolve the error The minCompileSdk 31 specified in a dependency's AAR metadata in native Java or Kotlin?

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.