5

equals()方法(就此而言,也是该compareTo()方法)可以成为性能热点(例如,在高流量中HashMap)。我想知道人们在证明必要时采用了哪些技巧来针对这些情况优化这些方法。

例如,IntelliJ IDEA 生成以下内容:

public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;

    ...
}

您还遇到什么可以作为编写良好执行equals()方法的指南?

4

7 回答 7

14

一些不一定特定于equals()

  • 尽早失败。与您发布的片段类似,首先从最广泛的排除标准开始,然后变得更细粒度,以便该方法可以尽快返回
  • 仅比较相等性所需的属性。我有时看到人们比较一个类提供的每一条信息,即使只有少数属性实际上对两个类实例的相等性起语义作用。这当然在很大程度上取决于您的课程和设计
  • 尽可能避免相等递归。根据您要比较的类属性类型,您可能会陷入递归调用equals()自己或其他对象的情况,这可能会产生隐藏的性能影响

除了性能考虑之外,不要忘记equalsAPI 契约以确保您的相等性是自反的、对称的、传递的和一致hashcode()的,并且在您覆盖时也始终覆盖equals()

于 2009-07-22T01:27:24.860 回答
5

How to Write an Equality Method in Java是一篇非常详细且写得很好的文章,解释了编写相等方法的常见陷阱以及如何避免它们。

于 2009-07-22T02:59:41.263 回答
4

我认为您已经掌握了其中的关键部分,因为您说:

...当他们证明有必要时。

记住优化的一般规则:

  1. 不要……还
  2. 优化前的配置文件

几年前我在课堂上听过它们,而且我可以说C2是来源。

于 2009-07-22T01:30:06.590 回答
2

查看 Joshua Bloch 的书“Effective Java”。它有一些惊人的技巧和关于这个问题的整个部分。祝你好运!

于 2009-07-22T01:40:37.123 回答
1

您可能会从string interning中得到启发。

如果您的对象是不可变的,您可以通过使用静态工厂方法并将唯一实例填充到哈希表中来实现自己的“实习”。如果你这样做,那么当引用相等时,对象也相等。

于 2009-07-22T01:41:02.673 回答
1

如果您的对象在您可以完全控制equals()对它们的调用的环境中,那么您应该跟踪您正在执行的比较类型,并equals()适当地调整您的方法。

您也许可以确认某些情况永远不会发生,因此不需要为 within 编码equals(),例如:

  • 比较null
  • 比较不同类型
  • 比较自我

您还可以决定执行检查的适当顺序,首先检查最常见的失败原因。

于 2009-07-22T02:04:31.243 回答
0

我建议使 HashMap 更大是 equals() 是昂贵的(例如通过降低负载因子)。这样你就会有更少的冲突,并且希望 if(o == this) return true 最常匹配。

于 2009-07-22T05:55:08.153 回答