JAVA中對象常見的幾種方法比較
引言
- 對象比較是 Java 編程中基礎且核心的能力,它直接關系到集合元素的查找、排序、去重,以及業(yè)務邏輯中對象相等性的判斷,是保證程序邏輯正確性和數(shù)據(jù)一致性的關鍵環(huán)節(jié)。
- 今天就帶分享幾個常見的幾種比較,全文無尿點,讓我們開始吧~
基本元素比較
Java 中基本元素(基本數(shù)據(jù)類型 + 對應的包裝類 + 常用引用類型如 String)的比較規(guī)則,可以總結為以下核心要點:
1. 基本數(shù)據(jù)類型:直接用==比較值
Java 的 8 種基本數(shù)據(jù)類型(byte、short、int、long、float、double、char、boolean),只能用 == 比較值是否相等,不存在 equals() 方法。
int a = 10; int b = 10; System.out.println(a == b); // true,值相等
- 注意:不同基本類型比較時會發(fā)生自動類型提升,比如
int和long比較,int會提升為long后再比。
2. 包裝類:分兩種情況
包裝類(Integer、Long、Boolean 等)是引用類型,但有常量池緩存機制,比較規(guī)則需區(qū)分場景:
| 比較方式 | 適用場景 | 規(guī)則說明 |
|---|---|---|
== | 緩存范圍內的包裝類對象 | 對于 Integer(-128 ~ 127)、Boolean(true/false)等,緩存池內的對象用 == 會返回 true |
== | 緩存范圍外的包裝類對象 | 會創(chuàng)建新對象,== 比較的是地址,返回 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
3. String 類型:核心看==和equals()的區(qū)別
String 是引用類型,且有字符串常量池,比較規(guī)則是 Java 面試高頻考點:
==:比較的是對象的內存地址- 直接賦值的字符串(如
String s = "abc")會存入常量池,相同內容的字符串指向同一個地址。 new創(chuàng)建的字符串(如String s = new String("abc"))會在堆中創(chuàng)建新對象,地址不同。
- 直接賦值的字符串(如
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,內容相同
基本元素比較的核心建議
- 基本數(shù)據(jù)類型:直接用
==即可。 - 包裝類和
String:優(yōu)先用equals()比較內容,避免因緩存/常量池機制導致的邏輯錯誤。 - 包裝類和基本類型混合比較:包裝類會自動拆箱為基本類型,用
==直接比的值。Integer i = 10; int j = 10; System.out.println(i == j); // true,i 自動拆箱為 int
總結
- 對象比較的最佳實踐總結
- 不同場景下的選擇建議
- 未來Java版本中可能的改進
提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔
對象的比較
Java 中自定義對象的比較,核心圍繞 內容相等性判斷 和 大小關系排序 兩大需求,對應四種實現(xiàn)方式,其中前三種是開發(fā)中最常用的:
1. 覆寫基類Object的equals()+hashCode()
核心用途
判斷兩個對象的內容是否相等,是集合去重、條件判斷的基礎。
核心規(guī)則
equals():默認比較對象地址(==),需重寫為基于核心業(yè)務屬性(如用戶 ID、訂單號)的比較邏輯。hashCode():必須和equals()保持一致(規(guī)范要求:equals相等的對象,hashCode必須相同),否則HashSet/HashMap等哈希集合會失效。
實現(xiàn)要點
- 自反性:
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時的必要操作。
2. 基于Comparable接口的比較
核心用途
定義對象的自然排序規(guī)則(默認排序規(guī)則),讓對象“天生可比較”。
核心方法
實現(xiàn) int compareTo(T o) 方法:
- 返回 正數(shù):當前對象 > 目標對象。
- 返回 0:當前對象 = 目標對象。
- 返回 負數(shù):當前對象 < 目標對象。
實現(xiàn)要點
- 排序規(guī)則基于業(yè)務核心屬性(如按用戶 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> {
@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<>();
// 假設已經(jīng)往 userList 里加了一些 User 對象Collections.sort (userList, new UserNameLengthComparator ());
- 好的,咱們再捋一遍。Collections.sort 這個方法,其實有兩種用法。第一種,只傳一個 List,這時候 List 里的每個對象,必須自己會 “比大小”,也就是實現(xiàn)了 Comparable 接口,重寫了 compareTo 方法。
- sort 方法會自動調用對象的 compareTo 來排順序。第二種,傳一個 List 再加一個 Comparator 比較器,這時候對象自己會不會比大小無所謂,sort 方法會用你傳的比較器里的規(guī)則來排。簡單說就是,不傳比較器,就用對象自己的 compareTo;傳了比較器,就聽比較器的。
適用場景
- 對象有固定的默認排序規(guī)則(如用戶默認按 ID 排序、商品默認按價格排序)。
- 用于
Collections.sort(List)、TreeSet/TreeMap的默認排序。
3. 基于Comparator比較器的比較
核心用途
定義對象的定制排序規(guī)則,靈活擴展多種排序方式,不修改對象本身代碼。
核心方法
實現(xiàn) int compare(T o1, T o2) 方法,規(guī)則和 compareTo 一致。
實現(xiàn)形式
- 匿名內部類。
- Lambda 表達式(JDK 8+ 推薦)。
- 靜態(tài)工具類(如
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);
適用場景
- 對象需要多種排序規(guī)則(如用戶可按 ID、姓名、注冊時間排序)。
- 無法修改對象源碼(如第三方類),但需要排序。
- 用于
Collections.sort(List, Comparator)、TreeSet構造函數(shù)指定排序規(guī)則。
總結一下
| 比較方式 | 核心作用 | 靈活性 | 適用場景 |
|---|---|---|---|
equals() + hashCode() | 判斷內容相等 | 低 | 集合去重、邏輯相等判斷 |
Comparable | 自然排序(默認規(guī)則) | 低 | 對象有固定排序規(guī)則 |
Comparator | 定制排序(多規(guī)則) | 高 | 多種排序需求、第三方類排序 |
Objects.compare | 簡化比較 + 空指針防護 | 中 | JDK 8+ 簡潔排序代碼 |
選型口訣:
- 判相等:重寫
equals+hashCode。 - 單排序:實現(xiàn)
Comparable。 - 多排序:用
Comparator比較器。
可以理解Comparable 就是讓你的對象自己學會排序,比如 User 類實現(xiàn)了它,就相當于 User 自己知道 “我要按 id 排”。而 Comparator 呢,就是一個外部的排序小工具,你想讓 User 按名字排,就做一個按名字比較的小工具傳給排序方法,不用改 User 本身。一個是自帶技能,一個是外部工具.
到此這篇關于JAVA中對象常見的幾種方法比較的文章就介紹到這了,更多相關JAVA對象方法比較內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
IDEA下因Lombok插件產(chǎn)生的Library source does not match the bytecode報
這篇文章主要介紹了IDEA下因Lombok插件產(chǎn)生的Library source does not match the bytecode報錯問題及解決方法,親測試過好用,需要的朋友可以參考下2020-04-04

