How do I compare two Integers? [duplicate]
Asked Answered
O

9

34

I have to compare two Integer objects (not int). What is the canonical way to compare them?

Integer x = ...
Integer y = ...

I can think of this:

if (x == y) 

The == operator only compares references, so this will only work for lower integer values. But perhaps auto-boxing kicks in...?

if (x.equals(y)) 

This looks like an expensive operation. Are there any hash codes calculated this way?

if (x.intValue() == y.intValue())

A little bit verbose...

EDIT: Thank you for your responses. Although I know what to do now, the facts are distributed on all of the existing answers (even the deleted ones :)) and I don't really know, which one to accept. So I'll accept the best answer, which refers to all three comparison possibilities, or at least the first two.

Orifice answered 9/12, 2009 at 13:18 Comment(5)
You shouldn't use Integer x = ... in the first place, use int x = ... instead.Leisaleiser
That was only an example to show the type of x and y. Actually those values come from a List<Integer> where a can't use int.Orifice
Shall I compare thee to a summer's day?Construction
@starblue: The primitive wrapper classes exist for a (very good) reason. "You shouldn't use Integer x = ... in the first place" sounds misguided at best.Improvident
The wrappers exist for putting integer objects into data structures, not for variables containing a single integer.Leisaleiser
P
34

This is what the equals method does:

public boolean equals(Object obj) {
    if (obj instanceof Integer) {
        return value == ((Integer)obj).intValue();
    }
    return false;
}

As you can see, there's no hash code calculation, but there are a few other operations taking place there. Although x.intValue() == y.intValue() might be slightly faster, you're getting into micro-optimization territory there. Plus the compiler might optimize the equals() call anyway, though I don't know that for certain.

I generally would use the primitive int, but if I had to use Integer, I would stick with equals().

Pithos answered 9/12, 2009 at 15:1 Comment(1)
While this works for non-null values, it will fail if the calling object is itself null. I've yet to find an elegant way to compare "possibly-null" objects.Amnion
A
26

Use the equals method. Why are you so worried that it's expensive?

Allative answered 9/12, 2009 at 13:21 Comment(6)
Not in absolute terms, but considering how inexpensive an integer comparison on assembly level is, I thought it can only get much worse.Orifice
Don't concern yourself with micro-optimization.Hopple
So what exactly do you thing Integer.equals() does? I put my bet on "a.value==b.value"Catholicism
@ammoQ: Essentially it does that, but there seems to be an if-clause with instanceof operation, a cast of b to Integer, and call to its intValue() method. So it definitely is more expensive than a primitive integer comparison.Chophouse
@Joonas: But that sounds like something the JIT compiler in the JVM would take care of pretty easy anyway?Strickland
As Reverend Gonzo says, one shouldn't get into micro-optimizations. If, after writing your program, you find that's it's too slow then you profile it. Only then will you know what things to optimize. I've fooled myself so many times thinking I knew where the bottlenecks were in a program only to find that I was completely wrong. Optimize only after profiling peope!Allative
F
13
if (x.equals(y))

This looks like an expensive operation. Are there any hash codes calculated this way?

It is not an expensive operation and no hash codes are calculated. Java does not magically calculate hash codes, equals(...) is just a method call, not different from any other method call.

The JVM will most likely even optimize the method call away (inlining the comparison that takes place inside the method), so this call is not much more expensive than using == on two primitive int values.

Note: Don't prematurely apply micro-optimizations; your assumptions like "this must be slow" are most likely wrong or don't matter, because the code isn't a performance bottleneck.

Ferdinande answered 9/12, 2009 at 13:32 Comment(1)
equals is a instanceof check, a cast and a call to intValue(), before the real ==. Sure not a reason to do some premature optimization.Adamson
L
9

Minor note: since Java 1.7 the Integer class has a static compare(Integer, Integer) method, so you can just call Integer.compare(x, y) and be done with it (questions about optimization aside).

Of course that code is incompatible with versions of Java before 1.7, so I would recommend using x.compareTo(y) instead, which is compatible back to 1.2.

Lignin answered 12/12, 2013 at 23:27 Comment(0)
L
8

I would go with x.equals(y) because that's consistent way to check equality for all classes.

As far as performance goes, equals is actually more expensive because it ends up calling intValue().

EDIT: You should avoid autoboxing in most cases. It can get really confusing, especially the author doesn't know what he was doing. You can try this code and you will be surprised by the result;

Integer a = 128;
Integer b = 128;

System.out.println(a==b);
Leontina answered 9/12, 2009 at 13:21 Comment(0)
M
3

Compare integer and print its value in value ascending or descending order. All you have to do is implements Comparator interface and override its compare method and compare its value as below:

@Override
public int compare(Integer o1, Integer o2) {
    if (ascending) {
        return o1.intValue() - o2.intValue();
    } else {
        return o2.intValue() - o1.intValue();
    }

}
Margherita answered 6/4, 2014 at 21:12 Comment(1)
note that this does not work if operations overflow.Sayyid
U
2

"equals" is it. To be on the safe side, you should test for null-ness:

x == y || (x != null && x.equals(y))

the x==y tests for null==null, which IMHO should be true.

The code will be inlined by the JIT if it is called often enough, so performance considerations should not matter.

Of course, avoiding "Integer" in favor of plain "int" is the best way, if you can.

[Added]

Also, the null-check is needed to guarantee that the equality test is symmetric -- x.equals(y) should by the same as y.equals(x), but isn't if one of them is null.

Unfaithful answered 9/12, 2009 at 13:52 Comment(2)
It's almost always better to just let a NullPointerException throw if a reference is null.Slowdown
But you surely would not use "Integer" instead of "int" if there was was no valid situation where the value is null?Unfaithful
V
1

The Integer class implements Comparable<Integer>, so you could try,

x.compareTo(y) == 0

also, if rather than equality, you are looking to compare these integers, then,

x.compareTo(y) < 0 will tell you if x is less than y.

x.compareTo(y) > 0 will tell you if x is greater than y.

Of course, it would be wise, in these examples, to ensure that x is non-null before making these calls.

Vitalize answered 9/12, 2009 at 18:51 Comment(0)
M
1

I just encountered this in my code and it took me a while to figure it out. I was doing an intersection of two sorted lists and was only getting small numbers in my output. I could get it to work by using (x - y == 0) instead of (x == y) during comparison.

Maryannmaryanna answered 18/4, 2015 at 3:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.