JAVA中对象常见的几种方法比较
<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>引言</li><li>基本元素比较</li><ul class="second_class_ul"><li>1. 基本数据类型:直接用==比较值</li><li>2. 包装类:分两种情况</li><li>3. String 类型:核心看==和equals()的区别</li><ul class="third_class_ul"><li>基本元素比较的核心建议</li><li>总结</li></ul></ul><li>对象的比较</li><ul class="second_class_ul"><li>1. 覆写基类Object的equals()+hashCode()</li><ul class="third_class_ul"><li>核心用途</li><li>核心规则</li><li>实现要点</li><li>示例</li><li>适用场景</li></ul><li>2. 基于Comparable接口的比较</li><ul class="third_class_ul"><li>核心用途</li><li>核心方法</li><li>实现要点</li><li>示例</li><li>适用场景</li></ul><li>3. 基于Comparator比较器的比较</li><ul class="third_class_ul"><li>核心用途</li><li>核心方法</li><li>实现形式</li><li>示例</li><li>适用场景</li></ul><li>总结一下</li><ul class="third_class_ul"></ul></ul></ul></div><p class="maodian"></p><h2>引言</h2><ul><li>对象比较是 Java 编程中基础且核心的能力,它直接关系到集合元素的查找、排序、去重,以及业务逻辑中对象相等性的判断,是保证程序逻辑正确性和数据一致性的关键环节。</li><li>今天就带分享几个常见的几种比较,全文无尿点,让我们开始吧~</li></ul>
<p class="maodian"></p><h2>基本元素比较</h2>
<p>Java 中<strong>基本元素</strong>(基本数据类型 + 对应的包装类 + 常用引用类型如 <code>String</code>)的比较规则,可以总结为以下核心要点:</p>
<p class="maodian"></p><h3>1. 基本数据类型:直接用==比较值</h3>
<p>Java 的 8 种基本数据类型(<code>byte</code>、<code>short</code>、<code>int</code>、<code>long</code>、<code>float</code>、<code>double</code>、<code>char</code>、<code>boolean</code>),<strong>只能用 == 比较值是否相等</strong>,不存在 <code>equals()</code> 方法。</p>
<div class="jb51code"><pre class="brush:java;">int a = 10;
int b = 10;
System.out.println(a == b); // true,值相等
</pre></div>
<ul><li>注意:不同基本类型比较时会发生<strong>自动类型提升</strong>,比如 <code>int</code> 和 <code>long</code> 比较,<code>int</code> 会提升为 <code>long</code> 后再比。</li></ul>
<p class="maodian"></p><h3>2. 包装类:分两种情况</h3>
<p>包装类(<code>Integer</code>、<code>Long</code>、<code>Boolean</code> 等)是引用类型,但有<strong>常量池缓存机制</strong>,比较规则需区分场景:</p>
<table><thead><tr><th>比较方式</th><th>适用场景</th><th>规则说明</th></tr></thead><tbody><tr><td><code>==</code></td><td>缓存范围内的包装类对象</td><td>对于 <code>Integer</code>(-128 ~ 127)、<code>Boolean</code>(<code>true</code>/<code>false</code>)等,缓存池内的对象用 <code>==</code> 会返回 <code>true</code></td></tr><tr><td><code>==</code></td><td>缓存范围外的包装类对象</td><td>会创建新对象,<code>==</code> 比较的是地址,返回 <code>false</code></td></tr><tr><td><code>equals()</code></td><td>所有包装类对象</td><td>比较的是<strong>底层基本类型的值</strong>,推荐使用</td></tr></tbody></table>
<p>示例:</p>
<div class="jb51code"><pre class="brush:java;">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
</pre></div>
<p class="maodian"></p><h3>3. String 类型:核心看==和equals()的区别</h3>
<p><code>String</code> 是引用类型,且有<strong>字符串常量池</strong>,比较规则是 Java 面试高频考点:</p>
<ul><li><strong><code>==</code></strong>:比较的是<strong>对象的内存地址</strong>
<ul><li>直接赋值的字符串(如 <code>String s = "abc"</code>)会存入常量池,相同内容的字符串指向同一个地址。</li><li><code>new</code> 创建的字符串(如 <code>String s = new String("abc")</code>)会在堆中创建新对象,地址不同。</li></ul></li><li><code>equals()</code>:重写过的方法,比较的是<strong>字符串的内容</strong>,推荐使用。</li></ul>
<p>示例:</p>
<div class="jb51code"><pre class="brush:java;">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,内容相同
</pre></div>
<p class="maodian"></p><h4>基本元素比较的核心建议</h4>
<ol><li>基本数据类型:直接用 <code>==</code> 即可。</li><li>包装类和 <code>String</code>:优先用 <code>equals()</code> 比较内容,避免因缓存/常量池机制导致的逻辑错误。</li><li>包装类和基本类型混合比较:包装类会<strong>自动拆箱</strong>为基本类型,用 <code>==</code> 直接比的值。<div class="jb51code"><pre class="brush:java;">Integer i = 10;
int j = 10;
System.out.println(i == j); // true,i 自动拆箱为 int
</pre></div></li></ol>
<p class="maodian"></p><h4>总结</h4>
<ul><li>对象比较的最佳实践总结</li><li>不同场景下的选择建议</li><li>未来Java版本中可能的改进</li></ul>
<blockquote><p>提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档</p></blockquote>
<p class="maodian"></p><h2>对象的比较</h2>
<p>Java 中自定义对象的比较,核心围绕 <strong>内容相等性判断</strong> 和 <strong>大小关系排序</strong> 两大需求,对应四种实现方式,其中前三种是开发中最常用的:</p>
<p class="maodian"></p><h3>1. 覆写基类Object的equals()+hashCode()</h3>
<p class="maodian"></p><p class="maodian"></p><p class="maodian"></p><h4>核心用途</h4>
<p>判断两个对象的<strong>内容是否相等</strong>,是集合去重、条件判断的基础。</p>
<p class="maodian"></p><h4>核心规则</h4>
<ul><li><code>equals()</code>:默认比较对象地址(<code>==</code>),需重写为基于<strong>核心业务属性</strong>(如用户 ID、订单号)的比较逻辑。</li><li><code>hashCode()</code>:必须和 <code>equals()</code> 保持一致(规范要求:<code>equals</code> 相等的对象,<code>hashCode</code> 必须相同),否则 <code>HashSet</code>/<code>HashMap</code> 等哈希集合会失效。</li></ul>
<p class="maodian"></p><p class="maodian"></p><h4>实现要点</h4>
<ol><li>自反性:<code>x.equals(x)</code> 必须返回 <code>true</code>。</li><li>对称性:<code>x.equals(y)</code> 和 <code>y.equals(x)</code> 结果一致。</li><li>传递性:<code>x.equals(y)</code> 且 <code>y.equals(z)</code>,则 <code>x.equals(z)</code>。</li><li>一致性:对象属性不变时,多次调用 <code>equals</code> 结果不变。</li><li>非空性:<code>x.equals(null)</code> 必须返回 <code>false</code>。</li></ol>
<p class="maodian"></p><p class="maodian"></p><p class="maodian"></p><h4>示例</h4>
<div class="jb51code"><pre class="brush:java;">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);
}
}
</pre></div>
<p class="maodian"></p><p class="maodian"></p><p class="maodian"></p><h4>适用场景</h4>
<ul><li>判断两个对象是否为“逻辑相等”(如判断两个用户是否是同一个人)。</li><li>作为 <code>HashSet</code> 元素、<code>HashMap</code> 的 <code>key</code> 时的必要操作。</li></ul>
<p class="maodian"></p><h3>2. 基于Comparable接口的比较</h3>
<h4>核心用途</h4>
<p>定义对象的<strong>自然排序规则</strong>(默认排序规则),让对象“天生可比较”。</p>
<p class="maodian"></p><p class="maodian"></p><h4>核心方法</h4>
<p>实现 <code>int compareTo(T o)</code> 方法:</p>
<ul><li>返回 <strong>正数</strong>:当前对象 > 目标对象。</li><li>返回 <strong>0</strong>:当前对象 = 目标对象。</li><li>返回 <strong>负数</strong>:当前对象 < 目标对象。</li></ul>
<h4>实现要点</h4>
<ul><li>排序规则基于业务核心属性(如按用户 ID 升序、按价格降序)。</li><li>需满足<strong>比较器一致性</strong>:<code>x.compareTo(y) == 0</code> 应和 <code>x.equals(y)</code> 结果一致(非强制,但推荐遵守)。</li></ul>
<h4>示例</h4>
<div class="jb51code"><pre class="brush:java;">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> {
@Overridepublic 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 ());
</pre></div>
<ul><li>好的,咱们再捋一遍。Collections.sort 这个方法,其实有两种用法。第一种,只传一个 List,这时候 List 里的每个对象,必须自己会 “比大小”,也就是实现了 Comparable 接口,重写了 compareTo 方法。</li><li>sort 方法会自动调用对象的 compareTo 来排顺序。第二种,传一个 List 再加一个 Comparator 比较器,这时候对象自己会不会比大小无所谓,sort 方法会用你传的比较器里的规则来排。简单说就是,不传比较器,就用对象自己的 compareTo;传了比较器,就听比较器的。 </li></ul>
<h4>适用场景</h4>
<ul><li>对象有固定的默认排序规则(如用户默认按 ID 排序、商品默认按价格排序)。</li><li>用于 <code>Collections.sort(List)</code>、<code>TreeSet</code>/<code>TreeMap</code> 的默认排序。</li></ul>
<p class="maodian"></p><h3>3. 基于Comparator比较器的比较</h3>
<h4>核心用途</h4>
<p>定义对象的<strong>定制排序规则</strong>,灵活扩展多种排序方式,不修改对象本身代码。</p>
<h4>核心方法</h4>
<p>实现 <code>int compare(T o1, T o2)</code> 方法,规则和 <code>compareTo</code> 一致。</p>
<p class="maodian"></p><h4>实现形式</h4>
<ul><li>匿名内部类。</li><li>Lambda 表达式(JDK 8+ 推荐)。</li><li>静态工具类(如 <code>Comparator.comparing</code>)。</li></ul>
<h4>示例</h4>
<div class="jb51code"><pre class="brush:java;">// 方式1:Lambda 表达式,按姓名长度降序
Comparator<User> nameLengthComparator = (u1, u2) ->
Integer.compare(u2.getName().length(), u1.getName().length());
// 方式2:工具类,按姓名升序
Comparator<User> nameComparator = Comparator.comparing(User::getName);
</pre></div>
<h4>适用场景</h4>
<ul><li>对象需要多种排序规则(如用户可按 ID、姓名、注册时间排序)。</li><li>无法修改对象源码(如第三方类),但需要排序。</li><li>用于 <code>Collections.sort(List, Comparator)</code>、<code>TreeSet</code> 构造函数指定排序规则。</li></ul>
<p class="maodian"></p><h3>总结一下</h3>
<table><thead><tr><th>比较方式</th><th>核心作用</th><th>灵活性</th><th>适用场景</th></tr></thead><tbody><tr><td><code>equals()</code> + <code>hashCode()</code></td><td>判断内容相等</td><td>低</td><td>集合去重、逻辑相等判断</td></tr><tr><td><code>Comparable</code></td><td>自然排序(默认规则)</td><td>低</td><td>对象有固定排序规则</td></tr><tr><td><code>Comparator</code></td><td>定制排序(多规则)</td><td>高</td><td>多种排序需求、第三方类排序</td></tr><tr><td><code>Objects.compare</code></td><td>简化比较 + 空指针防护</td><td>中</td><td>JDK 8+ 简洁排序代码</td></tr></tbody></table>
<p><strong>选型口诀</strong>:</p>
<ul><li>判相等:重写 <code>equals</code> + <code>hashCode</code>。</li><li>单排序:实现 <code>Comparable</code>。</li><li>多排序:用 <code>Comparator</code> 比较器。</li></ul>
<p><strong>可以理解Comparable 就是让你的对象自己学会排序,比如 User 类实现了它,就相当于 User 自己知道 “我要按 id 排”。而 Comparator 呢,就是一个外部的排序小工具,你想让 User 按名字排,就做一个按名字比较的小工具传给排序方法,不用改 User 本身。一个是自带技能,一个是外部工具.</strong></p>
<p>到此这篇关于JAVA中对象常见的几种方法比较的文章就介绍到这了,更多相关JAVA对象方法比较内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
<div class="art_xg">
<b>您可能感兴趣的文章:</b><ul><li>基于java中两个对象属性的比较</li><li>Java比较两个对象大小的三种方法详解</li><li>Java比较对象大小两种常用方法</li><li>Java比较两个对象是否相等的方法</li><li>Java各种比较对象的方式的对比总结</li><li>在Java中如何比较两个对象浅析</li><li>Java中对象的比较操作实例分析</li><li>Java 中比较对象的用法小结</li></ul>
</div>
</div>
<!--endmain-->
頁:
[1]