java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Java对象比较方式

Java中对象比较的五种方式详解

作者:yingjuxia.com

本文详细阐述了Java中对象比较的五种核心方式:==、equals、hashCode、Comparable和Comparator,分析了它们的用途、语义、性能和适用场景,并提供了面试中常问的问题的解答模板,需要的朋友可以参考下

在 Java 中,对象比较 主要有以下 4–5 种核心方式,它们用途、语义、性能、适用场景完全不同。面试中常被追问的顺序通常是:== → equals → hashCode → Comparable → Comparator。

下面按使用频率和重要性逐一拆解。

1. == (引用比较 / 身份比较)

2. equals() (逻辑相等 / 值比较)

equals 比较内容hashCode 是否同步重写
String字符序列是否相同
Integer数值是否相同
BigDecimal数值 + 精度是否相同
LocalDate年月日是否相同
Arrays内容逐个 equals(deepEquals 多维)
@Override
public boolean equals(Object o) {
    // 1. 引用相同 → 相等
    if (this == o) return true;
    
    // 2. 类型检查 + null 检查
    if (o == null || getClass() != o.getClass()) return false;
    
    // 3. 强制转换后逐字段比较(基本类型用 ==,对象用 equals)
    Person other = (Person) o;
    return age == other.age &&
           Objects.equals(name, other.name) &&
           Objects.equals(idCard, other.idCard);
}

3. hashCode() (散列码比较,常配合 equals 使用)

作用:为对象生成一个 int 值,主要用于哈希表(HashMap、HashSet、Hashtable 等)

核心契约(Object 文档原文):

  1. 同一个对象在生命周期内多次调用 hashCode(),返回值必须相同(前提:equals 使用的字段没变)
  2. 如果 a.equals(b) == true,则 a.hashCode() 必须等于 b.hashCode()
  3. 如果 a.equals(b) == false,不要求 hashCode 不同(但最好不同,以减少哈希冲突)

重写 equals 必须重写 hashCode 的原因:

2025–2026 推荐生成方式(IDE 自动生成或以下方式):

@Override
public int hashCode() {
    return Objects.hash(name, age, idCard);   // 最简洁、最推荐(Java 7+)
}

4. Comparable 接口(自然排序)

public class Person implements Comparable<Person> {
    private String name;
    private int age;

    @Override
    public int compareTo(Person o) {
        // 先按年龄升序,年龄相同再按姓名字典序
        int ageCmp = Integer.compare(this.age, o.age);
        if (ageCmp != 0) return ageCmp;
        return this.name.compareTo(o.name);
    }
}

5. Comparator 接口(定制排序 / 外部比较器)

// 方式一:Lambda + comparing
List<Person> list = ...;
list.sort(Comparator.comparingInt(Person::getAge)
                    .thenComparing(Person::getName));

// 方式二:匿名内部类(老项目常见)
Comparator<Person> byAgeThenName = (p1, p2) -> {
    int cmp = Integer.compare(p1.getAge(), p2.getAge());
    return cmp != 0 ? cmp : p1.getName().compareTo(p2.getName());
};

6. 快速对比总结表(面试最爱画的表)

比较方式比较内容是否可重写是否侵入类典型集合支持性能面试出现频率
==引用地址极高★★★★★
equals()逻辑相等(内容)HashMap/HashSet★★★★★
hashCode()散列值是(必须与equals一致)HashMap/HashSet极高★★★★☆
compareTo()自然排序大小TreeSet/TreeMap 默认★★★★
Comparator定制排序任意集合/Stream★★★★

7. 常见面试连环追问(建议准备的回答模板)

重写了 equals 没重写 hashCode 会有什么问题?
→ HashMap 中 put 后 get 找不到;Set 中出现重复元素

String 为什么可以直接用 == 比较常量池字符串?
→ 字符串常量池 + intern() 机制

如何比较两个对象是否“完全相等”(包括所有字段深比较)?
→ Apache Commons Lang → ReflectionToStringBuilder 或 Objects.deepEquals(多维数组)

Java 14+ Record 类自动实现了哪些比较相关方法?
→ equals、hashCode、toString 全部按所有组件字段自动生成

排序时如果 compareTo 返回 0,但 equals 返回 false 会怎样?
→ TreeSet/TreeMap 会认为相等而覆盖(违反 SortedSet 语义)

希望这份总结能帮你快速建立 Java 对象比较的完整知识图谱。

如果你正在准备面试,想针对某一种方式(比如 equals + hashCode 的完整手写实现、或 Comparator 的多种写法)要更详细的代码示例,或者想看某个具体场景的对比代码,直接告诉我,我可以继续展开。

以上就是Java中对象比较的五种方式详解的详细内容,更多关于Java对象比较方式的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文