數據結構 Java對象的比較

在Java中,凡是涉及到比較的,可以分為兩類情況:一類是基本數據類型的比較,另一類是引用數據類型的比較。對于基本數據類型的比較,我們通過關系運算符(==、>、<、!=、>=、<=)進行它們之間的比較,而對于引用數據類型,并不能簡單的通過關系運算符來進行它們的比較,因為引用數據類型如果使用關系運算符比較的話,比較的是它們的引用類型,并不是對象的內容。

本文就引用數據類型如何進行比較展開討論。

1.對象比較存在的問題

來看下面的例子:

class Card {public int rank;  //點數public String suit;  //花色public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}
}public class Test {public static void main(String[] args) {Card card1 = new Card(1,"方塊");Card card2 = new Card(2,"方塊");Card card3 = card1;System.out.println(card1 > card2);   //1.System.out.println(card1 == card2);  //2.System.out.println(card2 < card1);   //3.System.out.println(card1 == card3);  //4.}
}

對于代碼中的1.、2.、3.和4.語句,1.和3.不能通過編譯,2.和4.可以通過遍歷,并且運行結果分別是:false(因為card1和card2是不同的對象)、true(card1和card3是相同的對象)。

面對這個結果,我們易產生疑問:為什么Java中引用類型的變量不能直接按照<或者>進行比較,為什么==就可以呢

這是因為:對于我們用戶實現的自定義類型,都默認繼承Object類,而Object類中提供了equals方法,而==默認情況下調用equals方法,但是該方法的比較規則并沒有比較引用變量引用對象的內容,而是直接比較引用變量的地址

但是有些情況下,我們需要比較的是引用變量引用對象的內容,比如:向優先級隊列中插入某個對象時,需要比較對象的內容來進行調整堆,那這又該怎么辦呢?

2.對象比較的方式

對于上述所說的需要比較對象內容的情況,再根據具體的比較需要,有三種方案,它們分別是:

重寫父類的equals方法實現Comparable接口使用比較器Comparator接口

2.1 重寫父類的equals方法

該方案的核心用途:判斷兩個對象的內容是否 “邏輯相等”,是最基礎的對象內容比較方式。

適用場景:一般的對象內容比較(如判斷兩個Person是否為同一個人)

在上述的例子中,我們我們認為兩張牌的點數和花色一樣,就認為它們是同一張牌,那么重寫equals方法,再進行測試:

package demo1;import java.util.Objects;class Card {public int rank;  //點數public String suit;  //花色public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}@Overridepublic boolean equals(Object o) {//自己和自己比較if (this == o) {return true;}//如果是null對象或者o不是不是Card的子類if (o == null || getClass() != o.getClass()) {return false;}Card card = (Card) o;//比較點數和花色(花色是String類型,因此調用String的equals方法進行比較)return rank == card.rank && Objects.equals(suit, card.suit);}}public class Test {public static void main(String[] args) {Card card1 = new Card(1,"方塊");Card card2 = new Card(1,"方塊");Card card3 = card1;System.out.println(card1.equals(card2));System.out.println(card1.equals(card3));}
}//運行結果
true
true

代碼解讀:

  1. 如果指向同一個對象,返回 true
  2. 如果傳入的為 null,返回 false
  3. 如果傳入的對象類型不是 Card,返回 false
  4. 按照類的實現目標完成比較,例如這里只要花色和數值一樣,就認為是相同的牌
  5. 注意下調用其他引用類型的比較也需要 equals,例如這里的 suit 的比較

注意:重寫父類equal的方式雖然可以比較,但缺陷是:equal只能按照相等進行比較,不能按照大于、小于的方式進行比較,也就是說只能比較兩個東西是不是同一個。

2.2 實現Comparable接口

該方案的核心用途:為類定義 “默認排序規則”,讓對象自身具備可比較性。

適用場景:對象有明確的 “自然順序”(如學生按學號排序、商品按價格排序),且排序規則相對固定。

Comparable是JDK提供的泛型的比較接口類,它的源碼如下:

public interface Comparable<E> {

????????// 返回值:

????????// < 0: 表示 this 指向的對象小于 o 指向的對象

?????????// == 0: 表示 this 指向的對象等于 o 指向的對象

?????????// > 0: 表示 this 指向的對象大于 o 指向的對象

}

對于我們用戶自定義類型,如果想要按照大小進行比較時:在定義類時,實現Comparable接口即可,然后在類中重寫CompareTo方法。像這樣:

class Card implements Comparable<Card>{public int rank;  //點數public String suit;  //花色public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}//不在意花色,進行點數的比較@Overridepublic int compareTo(Card o) {if (o == null) {return 1;}return rank - o.rank;}
}
public class Test {public static void main(String[] args) {Card card1 = new Card(2,"梅花");Card card2 = new Card(3,"方塊");Card card3 = new Card(2,"方塊");System.out.println(card1.compareTo(card2));  // < 0,說明card1小于card2System.out.println(card1.compareTo(card3));  //== 0,說明card1等于card3System.out.println(card2.compareTo(card3));  // > 0,說明card2大于card3}
}//運行結果
-1
0
1

【注意】Comparable是Java.lang中的接口類,可以直接使用。

2.3 使用比較器Comparator接口

該方案的核心用途:為類定義 “臨時 / 額外的排序規則”,不修改原類代碼。

適用場景

  • 需要多種排序規則(如Person既可以按年齡排,也可以按姓名排);
  • 無法修改原類代碼(如第三方庫的類);
  • 優先級隊列(PriorityQueue)的元素排序(建大根堆需要)。

按照比較器方式進行比較,具體的操作如下:

1.用戶自定義比較器類,實現Comparator接口

public interface Comparator {

????????// 返回值:

????????// < 0: 表示 o1 指向的對象小于 o2 指向的對象

????????// == 0: 表示 o1 指向的對象等于 o2 指向的對象

? ? ? ??// > 0: 表示 o1 指向的對象等于 o2 指向的對象

????????int compare(T o1, T o2);

}

2.重寫Comparator中的compare方法

舉個例子:

import java.util.Comparator;class Card {public int rank;  //點數public String suit;  //花色public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}
}//自定義比較器類
class CardComparator implements Comparator<Card> {//重寫compare方法//依舊按照數值比較@Overridepublic int compare(Card o1, Card o2) {//如果兩張牌數值一樣if (o1.rank == o2.rank) {return 0;}//如果第一種牌為nullif (o1 == null) {return -1;}//如果第二張牌為nullif (o2 == null) {return 1;}//正常情況return o1.rank - o2.rank;}
}
public class Test {public static void main(String[] args) {Card card1 = new Card(1,"方塊");Card card2 = new Card(2,"方塊");Card card3 = new Card(1,"方塊");//定義比較器對象CardComparator cardComparator = new CardComparator();System.out.println(cardComparator.compare(card1,card3)); // == 0,說明兩張牌相等System.out.println(cardComparator.compare(card1,card2)); // < 0,說明card1小于card2System.out.println(cardComparator.compare(card2,card1)); // > 0,說明card2大于card1}
}//運行結果
0
-1
1

【注意】Comparator是java.util 包中的泛型接口類,使用時必須導入對應的包。

2.4 三種方式的對比

重寫的方法說明
Object.equals因為所有類都是繼承自 Object 的,所以直接覆寫即可,不過只能比較相等與 否
Comparable.compareTo

需要手動實現接口,侵入性比較強,但一旦實現,每次用該類都有順序,屬于內部順序

Comparator.compare需要實現一個比較器對象,對待比較類的侵入性弱,但對算法代碼實現侵入性 強

到此,關于如何去比較引用數據類型變量這個問題已經得到解決,我們有三種方案,按需使用即可!感謝您的閱讀,如有錯誤,還請指出!謝謝!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/96763.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/96763.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/96763.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

企智匯建筑施工項目管理系統:全周期數字化管控,賦能工程企業降本增效!?建筑工程項目管理軟件!建筑工程項目管理系統!建筑項目管理軟件企智匯軟件

在建筑施工行業&#xff0c;項目進度滯后、成本超支、質量安全隱患頻發、多方協同不暢等問題&#xff0c;一直是制約企業發展的痛點。傳統依賴人工記錄、Excel 統計的管理模式&#xff0c;不僅效率低下&#xff0c;更易因信息斷層導致決策失誤。企智匯建筑施工項目管理系統憑借…

k8s-臨時容器學習

臨時容器學習1. 什么是臨時容器2. 實驗1. 什么是臨時容器 在官網&#xff1a;https://kubernetes.io/zh-cn/docs/concepts/workloads/pods/ephemeral-containers/ 中有介紹 臨時容器是用于調試Pod中崩潰的容器或者不具備調試工具&#xff0c;比如在一個運行著業務的容器中&am…

Python 2025:低代碼開發與自動化運維的新紀元

從智能運維到無代碼應用&#xff0c;Python正在重新定義企業級應用開發范式在2025年的企業技術棧中&#xff0c;Python已經從一個"開發工具"演變為業務自動化的核心平臺。根據Gartner 2025年度報告&#xff0c;68%的企業在自動化項目中使用Python作為主要開發語言&am…

Netty 在 API 網關中的應用篇(請求轉發、限流、路由、負載均衡)

Netty 在 API 網關中的應用篇&#xff08;請求轉發、限流、路由、負載均衡&#xff09;隨著微服務架構的普及&#xff0c;API 網關成為服務之間通信和安全控制的核心組件。在構建高性能網關時&#xff0c;Netty 因其高吞吐、低延遲和異步非阻塞 IO 的特性&#xff0c;成為不少開…

基于STM32設計的青少年學習監控系統(華為云IOT)_282

文章目錄 一、前言 1.1 項目介紹 【1】項目開發背景 【2】設計實現的功能 【3】項目硬件模塊組成 【4】設計意義 【5】國內外研究現狀 【6】摘要 1.2 設計思路 1.3 系統功能總結 1.4 開發工具的選擇 【1】設備端開發 【2】上位機開發 1.5 參考文獻 1.6 系統框架圖 1.7 系統原理…

手寫Spring底層機制的實現【初始化IOC容器+依賴注入+BeanPostProcesson機制+AOP】

摘要&#xff1a;建議先看“JAVA----Spring的AOP和動態代理”這個文章&#xff0c;解釋都在代碼中&#xff01;一&#xff1a;提出問題依賴注入1.單例beans.xml<?xml version"1.0" encoding"UTF-8"?> <beans xmlns"http://www.springframe…

5G NR-NTN協議學習系列:NR-NTN介紹(2)

NTN網絡作為依賴衛星的通信方式&#xff0c;需要面對的通信距離&#xff0c;通信雙方的移動速度都和之前TN網絡存在巨大差異。在距離方面相比蜂窩地面網絡Terrestrial Network通信距離從最小幾百米到最大幾十km的情況&#xff0c;NTN非地面網絡的通信距離即使是近地軌道的LEO衛…

線掃相機采集圖像起始位置不正確原因總結

1、幀觸發開始時間問題 問題描述: 由于幀觸發決定了線掃相機的開始采集圖像位置,比如正確的位置是A點開始采集,結果你從B點開始觸發幀信號,這樣出來的圖像起始位置就不對 解決手段: 軟件需要記錄幀觸發時軸的位置 1)控制卡控制軸 一般使用位置比較觸發,我們可以通過監…

校園管理系統練習項目源碼-前后端分離-【node版】

今天給大家分享一個校園管理系統&#xff0c;前后端分離項目。這是最近在練習前端編程&#xff0c;結合 node 寫的一個完整的項目。 使用的技術&#xff1a; Node.js&#xff1a;版本要求16.20以上。 后端框架&#xff1a;Express框架。 數據庫&#xff1a; MySQL 8.0。 Vue2&a…

【項目】 :C++ - 仿mudou庫one thread one loop式并發服務器實現(模塊劃分)

【項目】 &#xff1a;C - 仿mudou庫one thread one loop式并發服務器實現一、HTTP 服務器與 Reactor 模型1.1、HTTP 服務器概念實現步驟難點1.2、Reactor 模型概念分類1. 單 Reactor 單線程2. 單 Reactor 多線程3. 多 Reactor 多線程目標定位總結二、功能模塊劃分2.1、SERVER …

浴室柜市占率第一,九牧重構數智衛浴新生態

作者 | 曾響鈴文 | 響鈴說2025年上半年&#xff0c;家居市場在政策的推動下展現出獨特的發展態勢。國家出臺的一系列鼓勵家居消費的政策&#xff0c;如“以舊換新”國補政策帶動超6000萬件廚衛產品煥新&#xff0c;以及我國超2.7億套房齡超20年的住宅進入改造周期&#xff0c;都…

源碼分析之Leaflet中TileLayer

概述 TileLayer 是 Layer 的子類&#xff0c;繼承自GridLayer基類&#xff0c;用于加載和顯示瓦片地圖。它提供了加載和顯示瓦片地圖的功能&#xff0c;支持自定義瓦片的 URL 格式和參數。 源碼分析 源碼實現 TileLayer的源碼實現如下&#xff1a; export var TileLayer GridL…

php學習(第二天)

一.網站基本概念-服務器 1.什么是服務器? 1.1定義 服務器&#xff08;server&#xff09;,也稱伺服器&#xff0c;是提供計算服務的設備。 供計算服務的設備” 這里的“設備”不僅指物理機器&#xff08;如一臺配有 CPU、內存、硬盤的計算機&#xff09;&#xff0c;也可以指…

C++(友元和運算符重載)

目錄 友元&#xff1a; 友元函數&#xff1a; 示例&#xff1a; 友元類&#xff1a; 示例&#xff1a; 優點&#xff1a; 注意事項&#xff1a; 運算符重載&#xff1a; 注意&#xff1a; 示例&#xff1a; 友元&#xff1a; C中如果想要外部函數或者類對一個類的pr…

和平精英風格射擊游戲開發指南

本教程將完整講解如何開發一款和平精英風格的HTML射擊游戲&#xff0c;涵蓋核心設計理念、代碼架構與關鍵實現細節。 核心設計架構 游戲機制系統 角色控制系統&#xff1a;通過鍵盤實現玩家移動戰斗系統&#xff1a;子彈發射與碰撞檢測道具系統&#xff1a;武器、彈藥和醫療包收…

21.1 《24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰》

24GB顯存搞定LLaMA2-7B指令微調:QLoRA+Flash Attention2.0全流程實戰 實戰 LLaMA2-7B 指令微調 一、指令微調技術背景 指令微調(Instruction Tuning)是大模型訓練中的關鍵技術突破點。與傳統全量微調(Full Fine-Tuning)相比,指令微調通過特定格式的指令-響應數據訓練,…

周志華《機器學習導論》第10章 降維與度量學習

https://www.lamda.nju.edu.cn/aml24fall/slides/Chap10.pptx 目錄 1.MDS (Multiple Dimensional Scaling) 多維縮放方法 2. 主成分分析 (Principal Component Analysis, PCA) 2.1 凸優化證明 2.2 人臉識別降維應用 3. 核化PCA 4. 流行學習 4.1 LLE 局部線性嵌入&#…

Kubernetes 彈性伸縮:深入講解 HPA 和 VPA

1. 介紹 Kubernetes 提供了多種資源管理方式&#xff0c;其中 彈性伸縮&#xff08;Auto-scaling&#xff09;是最重要的特性之一。彈性伸縮可以根據應用的負載變化自動調整 Pod 的數量和資源&#xff0c;以確保在高負載下應用能夠正常運行&#xff0c;而在低負載時節省資源。在…

大數據畢業設計選題推薦-基于大數據的家庭能源消耗數據分析與可視化系統-Hadoop-Spark-數據可視化-BigData

?作者主頁&#xff1a;IT畢設夢工廠? 個人簡介&#xff1a;曾從事計算機專業培訓教學&#xff0c;擅長Java、Python、PHP、.NET、Node.js、GO、微信小程序、安卓Android等項目實戰。接項目定制開發、代碼講解、答辯教學、文檔編寫、降重等。 ?文末獲取源碼? 精彩專欄推薦?…

【Spring】原理解析:Spring Boot 自動配置的核心機制與實戰剖析

一、引言在當今的 Java 開發領域&#xff0c;Spring Boot 憑借其快速搭建項目、簡化配置等優勢&#xff0c;成為了眾多開發者的首選框架。而 Spring Boot 自動配置作為其核心特性之一&#xff0c;極大地提升了開發效率&#xff0c;讓開發者能夠更專注于業務邏輯的實現。本文將深…