JAVA中对象的几种比较

JAVA中对象的几种比较
在这里插入图片描述

文章目录


引言

  • 对象比较是 Java 编程中基础且核心的能力,它直接关系到集合元素的查找、排序、去重,以及业务逻辑中对象相等性的判断,是保证程序逻辑正确性和数据一致性的关键环节。
  • 今天就带分享几个常见的几种比较,全文无尿点,让我们开始吧~

基本元素比较

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

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

Java 的 8 种基本数据类型(byteshortintlongfloatdoublecharboolean),只能用 == 比较值是否相等,不存在 equals() 方法。

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

2. 包装类:分两种情况

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

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

示例:

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

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

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

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

示例:

String s1 ="hello";String s2 ="hello";String s3 =newString("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版本中可能的改进
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

对象的比较

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

1. 覆写基类 Objectequals() + 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

示例

publicclassUser{privateLong id;privateString name;@Overridepublicbooleanequals(Object o){if(this== o)returntrue;if(o ==null||getClass()!= o.getClass())returnfalse;User user =(User) o;returnObjects.equals(id, user.id)&&Objects.equals(name, user.name);}@OverridepublicinthashCode(){returnObjects.hash(id, name);}}

适用场景

  • 判断两个对象是否为“逻辑相等”(如判断两个用户是否是同一个人)。
  • 作为 HashSet 元素、HashMapkey 时的必要操作。

2. 基于 Comparable 接口的比较

核心用途

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

核心方法

实现 int compareTo(T o) 方法:

  • 返回 正数:当前对象 > 目标对象。
  • 返回 0:当前对象 = 目标对象。
  • 返回 负数:当前对象 < 目标对象。

实现要点

  • 排序规则基于业务核心属性(如按用户 ID 升序、按价格降序)。
  • 需满足比较器一致性x.compareTo(y) == 0 应和 x.equals(y) 结果一致(非强制,但推荐遵守)。

示例

publicclassUserimplementsComparable<User>{privateLong id;privateString name;// 按 id 升序排序@OverridepublicintcompareTo(User o){returnthis.id.compareTo(o.id);}}publicclassUserNameLengthComparatorimplementsComparator<User>{@Overridepublicint 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 =newArrayList<>();// 假设已经往 userList 里加了一些 User 对象Collections.sort (userList, new UserNameLengthComparator ());
  • 好的,咱们再捋一遍。Collections.sort 这个方法,其实有两种用法。第一种,只传一个 List,这时候 List 里的每个对象,必须自己会 “比大小”,也就是实现了 Comparable 接口,重写了 compareTo 方法。
  • sort 方法会自动调用对象的 compareTo 来排顺序。第二种,传一个 List 再加一个 Comparator 比较器,这时候对象自己会不会比大小无所谓,sort 方法会用你传的比较器里的规则来排。简单说就是,不传比较器,就用对象自己的 compareTo;传了比较器,就听比较器的。

适用场景

  • 对象有固定的默认排序规则(如用户默认按 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 比较器。

可以理解Comparable 就是让你的对象自己学会排序,比如 User 类实现了它,就相当于 User 自己知道 “我要按 id 排”。而 Comparator 呢,就是一个外部的排序小工具,你想让 User 按名字排,就做一个按名字比较的小工具传给排序方法,不用改 User 本身。一个是自带技能,一个是外部工具.

  • 我是Dylan 希望对你有帮助
  • 无限进步~

Read more

高精度加法,高精度乘法,高精度除法,高精度减法,链表相加

高精度加法,高精度乘法,高精度除法,高精度减法,链表相加

文章目录 * 高精度加法 * 大数相加 * 题解 * 代码 * 高精度乘法 * 大数乘法 * 题解 * 代码 * 高精度除法 * 题解 * 代码 * 高精度减法 * 题解 * 代码 * 链表相加(二) * 题解 * 代码 * 总结 高精度加法 大数相加 题目链接 题解 1. 可以将字符串转换为一个一个的字符相加,注意进位,从后向前加,就是你小学的计算 2. 只要存在进位,就继续加,字符串长度不同,加到长的字符串结束为止 代码 // 解法一:classSolution{ public: string solve(string s, string t){ int a[100000]={ 0},b[100000]

By Ne0inhk
数据结构-单链表

数据结构-单链表

单链表 * 概念与结构 * 结点 * 链表的性质 * 链表的打印 * 实现单链表 * 头文件 * 源文件 * 单链表的打印 * 单链表申请新节点内存 * 尾插 * 头插 * 尾删 * 头删 * 查找 * 在指定位置之前插入数据 * 在指定位置之后插入数据 * 删除pos结点 * 删除pos之后的结点 * 销毁链表 * 链表的分类 * 代码地址 概念与结构 概念:链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 逻辑结构:线性 物理结构(存储结构):不一定是线性的 链表就类似一个火车,车头是哨兵位(可有可无),车厢是节点 * 将火车里的某节车厢去掉或加上,不会影响其他车厢,每节车厢都是独立存在的。 在链表⾥,每节“车厢”是什么样的呢? \color{red}{在链表⾥,每节“车厢”是什么样的呢?

By Ne0inhk
【算法通关指南:数据结构与算法篇】二叉树相关算法题:1.美国血统 American Heritage 2.二叉树问题

【算法通关指南:数据结构与算法篇】二叉树相关算法题:1.美国血统 American Heritage 2.二叉树问题

🔥小龙报:个人主页 🎬作者简介:C++研发,嵌入式,机器人方向学习者 ❄️个人专栏:《算法通关指南》 ✨ 永远相信美好的事情即将发生 文章目录 * 前言 * 一、美国血统 American Heritage * 1.1题目 * 1.2 算法原理 * 1.3代码 * 二、 二叉树问题 * 2.1题目 * 2.2 算法原理 * 2.3代码 * 总结与每日励志 前言 本专栏聚焦算法题实战,系统讲解算法模块:以《c++编程》,《数据结构和算法》《基础算法》《算法实战》 等几个板块以题带点,讲解思路与代码实现,帮助大家快速提升代码能力ps:本章节题目分两部分,比较基础笔者只附上代码供大家参考,其他的笔者会附上自己的思考和讲解,希望和大家一起努力见证自己的算法成长 一、

By Ne0inhk
【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

【优选算法】D&C-Mergesort-Harmonies:分治-归并的算法之谐

文章目录 * 1.概念解析 * 2.排序数组 * 3.交易逆序对的总数 * 4.计算右侧小于当前元素的个数 * 5.翻转对 * 希望读者们多多三连支持 * 小编会继续更新 * 你们的鼓励就是我前进的动力! 本篇是优选算法之分治-归并,简单来说就是一个不断分组排序再合并的过程 1.概念解析 🚩什么是分治-归并? 分治归并(基于分治思想的归并排序)是分治算法(Divide and Conquer)在排序问题中的经典应用,核心是通过 “拆分 - 排序 - 合并” 三步,将无序数组转化为有序数组,本质是 “化繁为简、再合简为繁” 的解题思路 2.排序数组 ✏️题目描述: ✏️示例: 传送门:排序数组 题解: 本质上分治归并就是一个后序遍历,而快排就是一个前序遍历,不断向下细分数组,然后从下往上把左右两分支的数组排序并合并,以此向上循环往复

By Ne0inhk