跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 对象比较详解:equals、hashCode、Comparable 与 Comparator

Java 对象比较涉及内容相等性判断与自然排序规则。基本类型使用 ==,引用类型优先 equals。自定义对象需重写 equals 和 hashCode 用于集合去重。实现 Comparable 接口定义自然排序,使用 Comparator 接口实现灵活定制排序。掌握这些机制可确保集合操作正确性及业务逻辑一致性。

星落发布于 2026/3/15更新于 2026/8/1742 浏览
Java 对象比较详解:equals、hashCode、Comparable 与 Comparator

Java 对象比较详解

基本元素比较

Java 中基本元素(基本数据类型 + 对应的包装类 + 常用引用类型如 String)的比较规则,可以总结为以下核心要点:

1. 基本数据类型:直接用 == 比较值

Java 的 8 种基本数据类型(byte、short、int、long、float、double、char、boolean),只能用 == 比较值是否相等,不存在 equals() 方法。

int a = 10;
int b = 10;
System.out.println(a == b); // true,值相等
  • 注意:不同基本类型比较时会发生自动类型提升,比如 int 和 long 比较,int 会提升为 long 后再比。

2. 包装类:分两种情况

包装类(Integer、Long、Boolean 等)是引用类型,但有常量池缓存机制,比较规则需区分场景:

比较方式适用场景规则说明
==缓存范围内的包装类对象对于 Integer(-128 ~ 127)、Boolean(true/false)等,缓存池内的对象用 == 会返回 true
==缓存范围外的包装类对象会创建新对象,== 比较的是地址,返回 false
equals()所有包装类对象比较的是底层基本类型的值,推荐使用

示例:

Integer i1 = 127;
Integer i2 = ;
System.out.println(i1 == i2); 
System.out.println(i1.equals(i2)); 

   ;
   ;
System.out.println(i3 == i4); 
System.out.println(i3.equals(i4)); 
127
// true,在缓存范围内
// true
Integer
i3
=
128
Integer
i4
=
128
// false,超出缓存范围
// true

3. String 类型:核心看 == 和 equals() 的区别

String 是引用类型,且有字符串常量池,比较规则是 Java 面试高频考点:

  • ==:比较的是对象的内存地址
    • 直接赋值的字符串(如 String s = "abc")会存入常量池,相同内容的字符串指向同一个地址。
    • new 创建的字符串(如 String s = new String("abc"))会在堆中创建新对象,地址不同。
  • equals():重写过的方法,比较的是字符串的内容,推荐使用。

示例:

String s1 = "hello";
String s2 = "hello";
String s3 = new String("hello");
System.out.println(s1 == s2); // true,常量池同一对象
System.out.println(s1 == s3); // false,地址不同
System.out.println(s1.equals(s3)); // true,内容相同
基本元素比较的核心建议
  1. 基本数据类型:直接用 == 即可。
  2. 包装类和 String:优先用 equals() 比较内容,避免因缓存/常量池机制导致的逻辑错误。

包装类和基本类型混合比较:包装类会自动拆箱为基本类型,用 == 直接比的值。

Integer i = 10;
int j = 10;
System.out.println(i == j); // true,i 自动拆箱为 int

对象的比较

Java 中自定义对象的比较,核心围绕 内容相等性判断 和 大小关系排序 两大需求,对应四种实现方式,其中前三种是开发中最常用的:

1. 覆写基类 Object 的 equals() + hashCode()

核心用途

判断两个对象的内容是否相等,是集合去重、条件判断的基础。

核心规则
  • equals():默认比较对象地址(==),需重写为基于核心业务属性(如用户 ID、订单号)的比较逻辑。
  • hashCode():必须和 equals() 保持一致(规范要求:equals 相等的对象,hashCode 必须相同),否则 HashSet/HashMap 等哈希集合会失效。
实现要点
  1. 自反性:x.equals(x) 必须返回 true。
  2. 对称性:x.equals(y) 和 y.equals(x) 结果一致。
  3. 传递性:x.equals(y) 且 y.equals(z),则 x.equals(z)。
  4. 一致性:对象属性不变时,多次调用 equals 结果不变。
  5. 非空性:x.equals(null) 必须返回 false。
示例
public class User {
    private Long id;
    private String name;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        User user = (User) o;
        return Objects.equals(id, user.id) && Objects.equals(name, user.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name);
    }
}
适用场景
  • 判断两个对象是否为'逻辑相等'(如判断两个用户是否是同一个人)。
  • 作为 HashSet 元素、HashMap 的 key 时的必要操作。

2. 基于 Comparable 接口的比较

核心用途

定义对象的自然排序规则(默认排序规则),让对象'天生可比较'。

核心方法

实现 int compareTo(T o) 方法:

  • 返回 正数:当前对象 > 目标对象。
  • 返回 0:当前对象 = 目标对象。
  • 返回 负数:当前对象 < 目标对象。
实现要点
  • 排序规则基于业务核心属性(如按用户 ID 升序、按价格降序)。
  • 需满足比较器一致性:x.compareTo(y) == 0 应和 x.equals(y) 结果一致(非强制,但推荐遵守)。
示例
public class User implements Comparable<User> {
    private Long id;
    private String name;

    // 按 id 升序排序
    @Override
    public int compareTo(User o) {
        return this.id.compareTo(o.id);
    }
}

public class UserNameLengthComparator implements Comparator<User> {
    @Override
    public int compare(User u1, User u2) {
        // 比较两个 User 对象名字的长度
        int len1 = u1.getName().length();
        int len2 = u2.getName().length();
        // 按名字长度升序排列,如果想降序就反过来减
        return len1 - len2;
    }
}

// 然后,当你需要排序的时候,比如对一个 List<User>进行排序,就可以把这个 Comparator 传进去:
List<User> userList = new ArrayList<>();
// 假设已经往 userList 里加了一些 User 对象
Collections.sort(userList, new UserNameLengthComparator());

当只传一个 List 给 Collections.sort 时,List 里的每个对象必须实现了 Comparable 接口。若传入 Comparator,则使用指定规则排序。

适用场景
  • 对象有固定的默认排序规则(如用户默认按 ID 排序、商品默认按价格排序)。
  • 用于 Collections.sort(List)、TreeSet/TreeMap 的默认排序。

3. 基于 Comparator 比较器的比较

核心用途

定义对象的定制排序规则,灵活扩展多种排序方式,不修改对象本身代码。

核心方法

实现 int compare(T o1, T o2) 方法,规则和 compareTo 一致。

实现形式
  • 匿名内部类。
  • Lambda 表达式(JDK 8+ 推荐)。
  • 静态工具类(如 Comparator.comparing)。
示例
// 方式 1:Lambda 表达式,按姓名长度降序
Comparator<User> nameLengthComparator = (u1, u2) -> Integer.compare(u2.getName().length(), u1.getName().length());

// 方式 2:工具类,按姓名升序
Comparator<User> nameComparator = Comparator.comparing(User::getName);
适用场景
  • 对象需要多种排序规则(如用户可按 ID、姓名、注册时间排序)。
  • 无法修改对象源码(如第三方类),但需要排序。
  • 用于 Collections.sort(List, Comparator)、TreeSet 构造函数指定排序规则。

总结一下

比较方式核心作用灵活性适用场景
equals() + hashCode()判断内容相等低集合去重、逻辑相等判断
Comparable自然排序(默认规则)低对象有固定排序规则
Comparator定制排序(多规则)高多种排序需求、第三方类排序
Objects.compare简化比较 + 空指针防护中JDK 8+ 简洁排序代码

选型口诀:

  • 判相等:重写 equals + hashCode。
  • 单排序:实现 Comparable。
  • 多排序:用 Comparator 比较器。

目录

  1. Java 对象比较详解
  2. 基本元素比较
  3. 1. 基本数据类型:直接用 == 比较值
  4. 2. 包装类:分两种情况
  5. 3. String 类型:核心看 == 和 equals() 的区别
  6. 基本元素比较的核心建议
  7. 对象的比较
  8. 1. 覆写基类 Object 的 equals() + hashCode()
  9. 核心用途
  10. 核心规则
  11. 实现要点
  12. 示例
  13. 适用场景
  14. 2. 基于 Comparable 接口的比较
  15. 核心用途
  16. 核心方法
  17. 实现要点
  18. 示例
  19. 适用场景
  20. 3. 基于 Comparator 比较器的比较
  21. 核心用途
  22. 核心方法
  23. 实现形式
  24. 示例
  25. 适用场景
  26. 总结一下
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Windows 10 企业版共存 Python 3.11 与 3.6 版本:环境配置实战与避坑指南
  • 云边端一体化解析:概念、原理与AI基础设施实践
  • 剑指 Offer 整数快速幂算法原理与实现
  • Stable Diffusion WebUI 本地部署与使用指南
  • OpenClaw 龙虾机器人本地部署与配置实战
  • Python 拼接地图瓦片常见错误及解决方案
  • 单链表实战:删除指定值、反转链表与查找中间节点
  • Linux 网络基础:局域网与跨网段通信原理
  • Python 在 Windows 上的安装与 PyCharm 配置指南
  • Video2Robot:从视频到机器人动作的端到端生成管道
  • 蚂蚁开源 Ring-lite:2.75B 激活参数轻量级推理模型
  • Kubernetes 集群管理与核心组件详解
  • C++ ODB ORM 框架使用指南
  • Linux 基础命令与 Java 项目部署流程
  • GitHub Copilot 在 VS Code 上的安装与高阶配置指南
  • Python pandas 数据透视表 pivot_table 详解与实战
  • 大模型时代程序员如何实现自我成长与进阶路径
  • LightRAG:基于图结构索引的智能检索增强生成系统
  • Linux 库制作与原理:从生成使用到 ELF 文件与链接解析
  • Microsoft Word 的 5 种视图详解:页面、阅读、Web 版式、大纲与草稿

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online