Java 中对象的几种比较方式
Java 中对象比较的核心方法。基本元素比较涉及基本数据类型使用==,包装类和 String 优先使用 equals() 比较内容。自定义对象比较主要通过覆写 Object 的 equals() 和 hashCode() 判断相等性,通过实现 Comparable 接口定义自然排序,或使用 Comparator 接口实现定制排序。文章提供了各类比较方式的代码示例、核心规则及适用场景,帮助开发者根据实际需求选择合适的比较策略。

Java 中对象比较的核心方法。基本元素比较涉及基本数据类型使用==,包装类和 String 优先使用 equals() 比较内容。自定义对象比较主要通过覆写 Object 的 equals() 和 hashCode() 判断相等性,通过实现 Comparable 接口定义自然排序,或使用 Comparator 接口实现定制排序。文章提供了各类比较方式的代码示例、核心规则及适用场景,帮助开发者根据实际需求选择合适的比较策略。

对象比较是 Java 编程中基础且核心的能力,它直接关系到集合元素的查找、排序、去重,以及业务逻辑中对象相等性的判断,是保证程序逻辑正确性和数据一致性的关键环节。
Java 中基本元素(基本数据类型 + 对应的包装类 + 常用引用类型如 String)的比较规则,可以总结为以下核心要点:
== 比较值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 后再比。包装类(Integer、Long、Boolean 等)是引用类型,但有常量池缓存机制,比较规则需区分场景:
| 比较方式 | 适用场景 | 规则说明 |
|---|---|---|
== | 缓存范围内的包装类对象 | 对于 Integer(-128 ~ 127)、Boolean(true/false)等,缓存池内的对象用 == 会返回 true |
== | 缓存范围外的包装类对象 | 会创建新对象,== 比较的是地址,返回 false |
equals() | 所有包装类对象 | 比较的是底层基本类型的值,推荐使用 |
示例:
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2); // true,在缓存范围内
System.out.println(i1.equals(i2)); // true
Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4); // false,超出缓存范围
System.out.println(i3.equals(i4)); // true
== 和 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,内容相同
== 即可。String:优先用 equals() 比较内容,避免因缓存/常量池机制导致的逻辑错误。包装类和基本类型混合比较:包装类会自动拆箱为基本类型,用 == 直接比的值。
Integer i = 10;
int j = 10;
System.out.println(i == j); // true,i 自动拆箱为 int
Java 中自定义对象的比较,核心围绕 内容相等性判断 和 大小关系排序 两大需求,对应四种实现方式,其中前三种是开发中最常用的:
Object 的 equals() + hashCode()判断两个对象的内容是否相等,是集合去重、条件判断的基础。
equals():默认比较对象地址(==),需重写为基于核心业务属性(如用户 ID、订单号)的比较逻辑。hashCode():必须和 equals() 保持一致(规范要求:equals 相等的对象,hashCode 必须相同),否则 HashSet/HashMap 等哈希集合会失效。x.equals(x) 必须返回 true。x.equals(y) 和 y.equals(x) 结果一致。x.equals(y) 且 y.equals(z),则 x.equals(z)。equals 结果不变。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 时的必要操作。Comparable 接口的比较定义对象的自然排序规则(默认排序规则),让对象'天生可比较'。
实现 int compareTo(T o) 方法:
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());
Collections.sort 方法有两种用法。第一种,只传一个 List,这时候 List 里的每个对象,必须自己会'比大小',也就是实现了 Comparable 接口,重写了 compareTo 方法。sort 方法会自动调用对象的 compareTo 来排顺序。第二种,传一个 List 再加一个 Comparator 比较器,这时候对象自己会不会比大小无所谓,sort 方法会用你传的比较器里的规则来排。简单说就是,不传比较器,就用对象自己的 compareTo;传了比较器,就听比较器的。
Collections.sort(List)、TreeSet/TreeMap 的默认排序。Comparator 比较器的比较定义对象的定制排序规则,灵活扩展多种排序方式,不修改对象本身代码。
实现 int compare(T o1, T o2) 方法,规则和 compareTo 一致。
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);
Collections.sort(List, Comparator)、TreeSet 构造函数指定排序规则。| 比较方式 | 核心作用 | 灵活性 | 适用场景 |
|---|---|---|---|
equals() + hashCode() | 判断内容相等 | 低 | 集合去重、逻辑相等判断 |
Comparable | 自然排序(默认规则) | 低 | 对象有固定排序规则 |
Comparator | 定制排序(多规则) | 高 | 多种排序需求、第三方类排序 |
Objects.compare | 简化比较 + 空指针防护 | 中 | JDK 8+ 简洁排序代码 |
选型口诀:
equals + hashCode。Comparable。Comparator 比较器。Comparable 就是让你的对象自己学会排序,比如 User 类实现了它,就相当于 User 自己知道'我要按 id 排'。而 Comparator 呢,就是一个外部的排序小工具,你想让 User 按名字排,就做一个按名字比较的小工具传给排序方法,不用改 User 本身。一个是自带技能,一个是外部工具。

微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online
将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online