如何比较两个整数?

34

我需要比较两个Integer对象(不是int)。有什么标准方法来比较它们吗?

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

我能想到这个方法:

if (x == y) 

==运算符仅比较引用,因此这仅适用于较低的整数值。但也许会启用自动装箱......?

if (x.equals(y)) 

看起来这是一个很昂贵的操作,是否有使用此方式计算哈希码的方法?

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

有点啰嗦...

编辑:谢谢你们的回答。虽然我现在知道该怎么做了,但是所有现有答案(包括已删除的答案:))中都分散着一些事实,我不太确定该接受哪一个。因此,我会接受最好的答案,它涉及到所有三种比较可能性,或者至少前两种。


2
你不应该首先使用"Integer x = ...",而应该使用"int x = ..."。 - starblue
1
那只是一个示例,展示了x和y的类型。实际上,这些值来自List<Integer>,因为我不能使用int。 - Daniel Rikowski
我应该将你与夏日相比吗? - Dexygen
@starblue:原始包装类存在的理由非常充分。声称“你一开始就不应该使用Integer x = ...”听起来至少是误导性的。 - Priidu Neemre
包装器存在的目的是将整数对象放入数据结构中,而不是用于包含单个整数的变量。 - starblue
9个回答

34

这就是 equals 方法的作用:

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

正如你所看到的,这里没有哈希码计算,但是还有一些其他操作。虽然 x.intValue() == y.intValue() 可能会稍微快一点,但那就进入了微小优化的领域。此外,编译器可能会优化 equals() 的调用,尽管我无法确定。

通常情况下我会使用原始类型 int,但如果必须使用 Integer,我会坚持使用 equals() 方法。


1
虽然这对于非空值有效,但如果调用对象本身为空,则会失败。我还没有找到一种优雅的方法来比较“可能为空”的对象。 - tbm

26

使用equals方法。你为什么担心它会很昂贵呢?


不是绝对意义上的,但考虑到汇编级别上整数比较是多么廉价,我认为情况只会更糟。 - Daniel Rikowski
10
不要过于关注微观优化。 - Reverend Gonzo
1
那么,你认为Integer.equals()到底是做什么的?我打赌是“a.value==b.value”。 - Erich Kitzmueller
@ammoQ:基本上它是那样做的,但似乎有一个带有instanceof运算符的if语句,将b强制转换为Integer,并调用其intValue()方法。因此,它肯定比原始整数比较要昂贵。 - Joonas Pulakka
1
@Joonas:但这似乎是JVM中的JIT编译器很容易处理的事情? - Hannes Ovrén
正如Gonzo牧师所说,我们不应该过于追求微观优化。如果你在编写程序后发现它运行得太慢,那么你需要对其进行性能分析。只有这样,你才会知道哪些地方需要进行优化。我曾经多次自欺欺人地认为我知道程序中的瓶颈在哪里,但最终发现我完全错了。因此,在性能分析之前不要轻易进行优化! - svenningsson

13
if (x.equals(y))
这看起来不是一个昂贵的操作,并且没有计算任何哈希码。Java不会神奇地计算哈希码,equals(...)只是一个方法调用,与任何其他方法调用没有区别。JVM很可能会优化掉这个方法调用(内联方法中发生的比较),因此这个调用不会比在两个原始的int值上使用==更昂贵。注意:不要过早地应用微观优化;像“这一定很慢”之类的假设很可能是错误的或者无关紧要,因为代码不是性能瓶颈。

2
equals是一个instanceof check,一个cast和对intValue()的调用,在真正的==之前。当然这不是进行过早优化的理由。 - user85421

9

小提示:自Java 1.7以来,Integer类具有静态compare(Integer,Integer)方法,因此您只需调用Integer.compare(x,y)即可完成(除了优化问题之外的问题)。

当然,该代码与1.7版本之前的Java版本不兼容,因此我建议改用x.compareTo(y),它向后兼容到1.2。


8

我建议使用x.equals(y)来检查所有类的相等性,因为这是一种一致的方式。

就性能而言,equals实际上更加昂贵,因为它最终会调用intValue()。

编辑:在大多数情况下应避免自动装箱。它可能会变得非常混乱,特别是当作者不知道他在做什么时。您可以尝试此代码,您会惊讶于结果;

Integer a = 128;
Integer b = 128;

System.out.println(a==b);

3

比较整数并按值的升序或降序打印其值。您只需要实现Comparator接口并覆盖其compare方法,然后按如下方式比较其值:

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

}

请注意,如果操作溢出,则此操作无效。 - mookid

2
"

equals" 是指相等。为了安全起见,您应该检查是否为空:

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

x==y这个测试用于判断null==null是否为真,我的看法是应该为真。

如果代码被频繁调用,则JIT将内联该代码,因此性能考虑不重要。

当然,如果可以的话,避免使用"Integer"而使用普通的"int"是最好的方法。

[添加]

此外,需要进行null检查以保证相等性测试是对称的 -- x.equals(y)应该与y.equals(x)相同,但如果它们中有一个为null,则不是。


如果一个引用为null,让它抛出NullPointerException异常通常是更好的选择。 - Kevin Bourrillion
1
但是如果没有有效的情况下值为null,你肯定不会使用“Integer”而不是“int”吧? - mfx

1

整数类实现了Comparable<Integer>,因此您可以尝试使用以下代码:

x.compareTo(y) == 0

另外,如果你想比较这些整数而不是判断它们是否相等,那么:

x.compareTo(y) < 0 将告诉你 x 是否小于 y。

x.compareTo(y) > 0 将告诉你 x 是否大于 y。

当然,在进行这些调用之前,确保 x 不为空会更明智。


1
我在我的代码中遇到了这个问题,花了一段时间才解决。我正在对两个已排序列表进行交集操作,但输出结果只有小数。我通过在比较过程中使用(x - y == 0)而不是(x == y)来使其正常工作。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接