【问题标题】:How do I compare two Integers? [duplicate]如何比较两个整数? [复制]
【发布时间】:2010-12-24 20:02:31
【问题描述】:

我必须比较两个Integer 对象(不是int)。比较它们的规范方法是什么?

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

我能想到这个:

if (x == y) 

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

if (x.equals(y)) 

这看起来像是一项昂贵的操作。有没有这样计算的哈希码?

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

有点冗长...

编辑:感谢您的回复。尽管我现在知道该做什么,但事实分布在所有现有答案(甚至已删除的答案上:)),我真的不知道该接受哪一个。所以我会接受最好的答案,它指的是所有三种比较可能性,或者至少是前两种。

【问题讨论】:

  • 你不应该首先使用 Integer x = ... ,而是使用 int x = ... 。
  • 这只是显示 x 和 y 类型的示例。实际上,这些值来自不能使用 int 的 List
  • 我可以把你比作夏日吗?
  • @starblue:原始包装类的存在是出于(非常好的)原因。 “你一开始就不应该使用 Integer x = ...” 听起来是误导。
  • 包装器用于将整数对象放入数据结构中,而不是用于包含单个整数的变量。

标签: java comparison object-comparison


【解决方案1】:

这就是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()

【讨论】:

  • 虽然这适用于非空值,但如果调用对象本身为空,它将失败。我还没有找到一种优雅的方法来比较“可能为空”的对象。
【解决方案2】:

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

【讨论】:

  • 不是绝对值,但考虑到汇编级别的整数比较是多么便宜,我认为它只会变得更糟。
  • 不要关心微优化。
  • 那么 Integer.equals() 到底做了什么?我赌“a.value==b.value”
  • @ammoQ:本质上它是这样做的,但似乎有一个带有 instanceof 操作的 if 子句,将 b 转换为 Integer,并调用它的 intValue() 方法。所以它肯定比原始整数比较更昂贵。
  • @Joonas:但这听起来像是 JVM 中的 JIT 编译器无论如何都会很容易处理的事情?
【解决方案3】:
if (x.equals(y))

这看起来像是一项昂贵的操作。有没有这样计算的哈希码?

这不是一个昂贵的操作,也没有计算哈希码。 Java 不会神奇地计算哈希码,equals(...) 只是一个方法调用,与其他任何方法调用没有区别。

JVM 很可能甚至会优化方法调用(内联发生在方法内部的比较),所以这个调用并不比在两个原始 int 值上使用 == 贵多少。

注意:不要过早地应用微优化;您的诸如“这一定很慢”之类的假设很可能是错误的或无关紧要,因为代码不是性能瓶颈。

【讨论】:

  • equals 是 instanceof checkcast 和对 intValue() 的调用,在真正的 == 之前。当然不是做一些过早优化的理由。
【解决方案4】:

小提示:从 Java 1.7 开始,Integer 类有一个静态的 compare(Integer, Integer) 方法,因此您只需调用 Integer.compare(x, y) 即可完成它(关于优化的问题除外)。

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

【讨论】:

    【解决方案5】:

    我会选择 x.equals(y),因为这是检查所有类是否相等的一致方法。

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

    编辑:在大多数情况下,您应该避免自动装箱。它会变得非常混乱,尤其是作者不知道他在做什么。你可以试试这段代码,你会对结果感到惊讶;

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

    【讨论】:

      【解决方案6】:

      “等于”就是它。为了安全起见,您应该测试是否为空:

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

      x==y 测试 null==null,恕我直言,这应该是真的。

      如果调用足够频繁,代码将由 JIT 内联,因此性能方面的考虑应该无关紧要。

      当然,如果可以的话,最好避免使用“Integer”而使用普通的“int”。

      [已添加]

      此外,需要空值检查来保证相等性测试是对称的——x.equals(y) 应该与 y.equals(x) 相同,但如果其中一个为空,则不是。

      【讨论】:

      • 如果引用为空,让 NullPointerException 抛出几乎总是更好。
      • 但是,如果不存在值为 null 的有效情况,您肯定不会使用“Integer”而不是“int”?
      【解决方案7】:

      比较整数并按值升序或降序打印其值。您所要做的就是实现 Comparator 接口并覆盖它的 compare 方法并比较它的值,如下所示:

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

      【讨论】:

      • 请注意,如果操作溢出,这将不起作用。
      【解决方案8】:

      Integer 类实现了Comparable<Integer>,所以你可以试试,

      x.compareTo(y) == 0
      

      另外,如果您希望比较这些整数而不是相等,那么,

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

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

      当然,在这些示例中,明智的做法是在进行这些调用之前确保 x 不为空。

      【讨论】:

        【解决方案9】:

        我刚刚在我的代码中遇到了这个问题,我花了一段时间才弄明白。我正在做两个排序列表的交集,并且在我的输出中只得到少量数字。在比较期间,我可以使用(x - y == 0) 而不是(x == y) 来让它工作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-06-05
          • 2013-05-30
          • 2012-09-15
          • 1970-01-01
          • 2010-11-02
          • 2019-09-08
          • 2015-08-29
          相关资源
          最近更新 更多