吃透Java所有比较方式:从==、equals到Comparable/Comparator,面试+开发全覆盖

发布时间:2026/7/7 1:50:41
吃透Java所有比较方式:从==、equals到Comparable/Comparator,面试+开发全覆盖 哈喽各位Java开发者我们日常写业务代码判断相等、比较大小是最高频的操作账号状态判断、列表排序、参数校验、枚举匹配……全都离不开比较。很多开发者一直搞不清楚几个基础问题和equals()到底有什么区别为什么阿里编码规范强制要求字符串比较常量放前面变量放后面对象排序到底用 Comparable 还是 Comparator两者怎么选0.10.2为什么不能用判断相等浮点数怎么正确比较数组、空对象比较有什么坑下面进行解答。一、基础分水岭Java两类数据类型比较逻辑完全不同想要学会比较首先分清Java两大数据类型这是所有比较逻辑的底层前提基本数据类型byte、short、int、long、float、double、char、boolean直接存储数据值引用数据类型String、数组、自定义实体类、集合栈中存内存地址堆中存真实数据二、等值比较 与 !1. 基本类型使用 基本类型没有内存地址一说 直接比较变量存储的字面量数值! 判断不相等int a 10; int b 10; System.out.println(a b); // true数值相等 char c1 A; char c2 65; System.out.println(c1 c2); // trueASCII码数值相等基本类型判断相等直接用 最简单最高效。2. 引用类型使用 重点面试高频引用类型用 只比较对象的内存地址不比较对象内部内容// 两个不同堆内存对象内容一致地址不同 String s1 new String(java); String s2 new String(java); System.out.println(s1 s2); // false地址不一样引用类型 只判断是不是同一个对象不判断内容是否一致。特殊特例字符串常量池、包装类缓存字面量定义String、[-128,127]区间Integer包装类会启用JVM缓存 结果为true这是缓存机制不是能比较内容三、对象内容相等equals() 方法1. 底层来源equals()是 Object 父类的原生方法所有Java类默认继承Object原生equals本质就是// Object类原生源码 public boolean equals(Object obj) { return (this obj); }也就是说自定义类不重写equals调用equals和用没有任何区别依旧比较内存地址。2. 重写equals实现内容比较JDK核心类已经提前帮我们重写好了equalsString、Integer、Double、所有包装类重写后直接比较对象内部数据内容。String s1 new String(java); String s2 new String(java); System.out.println(s1.equals(s2)); // true比较字符串内容自定义实体类必须手动重写 equals hashCode否则无法实现按业务字段比较对象3. 开发编码规范常量前置这是工作中最重要的编码习惯也是阿里Java开发手册强制规范比较字符串/固定常量时常量放前面变量放后面不推荐变量在前极易空指针NullPointerExceptionString username null; // 变量为nullnull没有任何方法直接抛出空指针异常 if(username.equals(admin)){}推荐常量在前安全无空指针String username null; // admin 是常量池对象永远非空底层自动兼容null参数 if(admin.equals(username)){}原理总结String的equals源码会优先判断入参是否为null入参为空直接返回false只要调用方常量不为null程序不会报错。4. 最优方案Objects.equals()Java7不用纠结前后顺序官方工具类全自动处理空指针生产环境首选// 顺序不影响结果内部自动判空 Objects.equals(username, admin);底层源码逻辑先判断地址再非空校验后调用equals生产环境优先使用四、大小比较基础运算符 对象排序比较器1. 基础大小运算符、、、仅支持基本数据类型 char类型不能用于任何对象比较double score 89.5; if(score 60){ System.out.println(及格); }2. 特殊避坑浮点数float/double禁止用比较二进制存储精度丢失经典BUGSystem.out.println(0.1 0.2 0.3); // 输出 false正确写法设置极小误差值判断数值差值区间// 10的-6次方作为误差阈值 final double EPS 1e-6; if(Math.abs((0.10.2)-0.3) EPS){ System.out.println(数值相等); }3. 对象大小比较集合排序核心实体类没有天然大小关系JDK提供两套对比方案面试必问区别① Comparable 内部比较器默认排序规则写在实体类内部定义默认、固定的排序规则重写compareTo()返回负数当前对象 传入对象返回0两个对象相等返回正数当前对象 传入对象public class Student implements ComparableStudent{ private Integer age; // 默认按年龄升序排序 Override public int compareTo(Student o) { return this.age - o.age; } }② Comparator 外部比较器灵活多规则外部定义、不侵入实体类适合临时排序、多套排序规则Java8支持Lambda简化写法// 按年龄降序年龄相同按姓名排序 list.sort(Comparator.comparingInt(Student::getAge).reversed() .thenComparing(Student::getName));两者选型固定全局排序、修改实体类用 Comparable临时排序、多套排序规则、不改动实体用 Comparator五、特殊场景数组比较比较数组内存地址Arrays.equals()一维数组逐元素对比内容Arrays.deepEquals()多维数组、嵌套数组对比int[] arr1 {1,2,3}; int[] arr2 {1,2,3}; System.out.println(Arrays.equals(arr1,arr2)); // true六、生产环境最佳实践总结基本类型等值判断直接用数字大小判断 基础运算符浮点数用误差区间判断普通对象/字符串等值优先Objects.equals(a,b)彻底规避空指针老项目无Objects工具常量放前面常量.equals(变量)自定义类重写equals必须同步重写hashCode集合对象排序固定规则Comparable临时多规则Comparator数组内容对比统一使用Arrays工具类方法不用七、结尾Java的比较看着简单其实遍布语法坑和线上BUG风险空指针、精度丢失、地址和内容混淆都是线上高频事故来源。记住核心本质比地址/基本值、equals比内容、比较器比对象大小、工具类规避空指针就能搞定所有Java比较场景。