ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

不说废话之java对象的比较

2021-09-19 09:02:09  阅读:164  来源: 互联网

标签:废话 java rank 比较 不说 suit println public Card


目录

一:为何要比较

二:元素的比较

1 基本类型的比较

 2 对象的比较

 三:对象的比较

1 覆写基类的equal

2 基于comparable接口类的比较

3 基于比较器的比较 

 四 小结


一:为何要比较

说到优先级队列, 优先级队列在插入元素时有个要求:插入的元素不能是 null 或者元素之间必须要能够 进行比较 ,为了简单起见,我们只是插入了 Integer 类型,那优先级队列中能否插入自定义类型对象呢?

class Card { public int rank ; // 数值 public String suit ; // 花色 public Card ( int rank , String suit ) { this . rank = rank ; this . suit = suit ; } } public class TestPriorityQueue { public static void TestPriorityQueue () { PriorityQueue < Card > p = new PriorityQueue <> (); p . offer ( new Card ( 1 , "♠" )); p . offer ( new Card ( 2 , "♠" )); } public static void main ( String [] args ) { TestPriorityQueue (); } }
优先级队列底层使用堆,而向堆中插入元素时,为了满足堆的性质,必须要进行元素的比较,而此时 Card 是没有办 法直接进行比较的,因此抛出异常。

二:元素的比较

1 基本类型的比较

在 Java 中,基本类型的对象可以直接比较大小。
public class TestCompare { public static void main ( String [] args ) { int a = 10 ; int b = 20 ; System . out . println ( a > b ); System . out . println ( a < b ); System . out . println ( a == b ); char c1 = 'A' ; char c2 = 'B' ; System . out . println ( c1 > c2 ); System . out . println ( c1 < c2 ); System . out . println ( c1 == c2 ); boolean b1 = true ; boolean b2 = false ; System . out . println ( b1 == b2 ); System . out . println ( b1 != b2 ); } }

 2 对象的比较

class Card { public int rank ; // 数值 public String suit ; // 花色 public Card ( int rank , String suit ) { this . rank = rank ; this . suit = suit ; } } public class TestPriorityQueue { public static void main ( String [] args ) { Card c1 = new Card ( 1 , "♠" ); Card c2 = new Card ( 2 , "♠" ); Card c3 = c1 ; //System.out.println(c1 > c2); // 编译报错 System . out . println ( c1 == c2 ); // 编译成功 ----> 打印 false ,因为 c1 和 c2 指向的是不同对象 //System.out.println(c1 < c2); // 编译报错 System . out . println ( c1 == c3 ); // 编译成功 ----> 打印 true ,因为 c1 和 c3 指向的是同一个对象 } }
c1 、 c2 和 c3 分别是 Card 类型的引用变量,上述代码在比较编译时: c1 > c2 编译失败 c1== c2 编译成功 c1 < c2 编译失败 从编译结果可以看出, Java 中引用类型的变量不能直接按照 > 或者 < 方式进行比较 。 那为什么 == 可以比较? 因为: 对于用户实现自定义类型,都默认继承自 Object 类,而 Object 类中提供了 equal 方法,而 == 默认情况下调 用的就是 equal 方法 ,但是该方法的比较规则是: 没有比较引用变量引用对象的内容,而是直接比较引用变量的地 ,但有些情况下该种比较就不符合题意。

 三:对象的比较

有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整 堆,那该如何处理呢?

1 覆写基类的equal

public class Card { public int rank ; // 数值 public String suit ; // 花色 public Card ( int rank , String suit ) { this . rank = rank ; this . suit = suit ; } @Override public boolean equals ( Object o ) { // 自己和自己比较 if ( this == o ) { return true ; } // o 如果是 null 对象,或者 o 不是 Card 的子类 if ( o == null || ! ( o instanceof Card )) { return false ; } // 注意基本类型可以直接比较,但引用类型最好调用其 equal 方法 Card c = ( Card ) o ; return rank == c . rank && suit . equals ( c . suit ); } }
注意: 一般覆写 equals 的套路就是上面演示的 1. 如果指向同一个对象,返回 true 2. 如果传入的为 null ,返回 false 3. 如果传入的对象类型不是 Card ,返回 false 4. 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌 5. 注意下调用其他引用类型的比较也需要 equals ,例如这里的 suit 的比较 覆写基类 equal 的方式虽然可以比较,但缺陷是: equal 只能按照相等进行比较,不能按照大于、小于的方式进行 比较

2 基于comparable接口类的比较

Comparble 是 JDK 提供的泛型的比较接口类,源码实现具体如下:

 

public interface Comparable < E > { // 返回值 : // < 0: 表示 this 指向的对象小于 o 指向的对象 // == 0: 表示 this 指向的对象等于 o 指向的对象 // > 0: 表示 this 指向的对象等于 o 指向的对象 int compareTo ( E o ); }
对用用户自定义类型,如果要想按照大小与方式进行比较时: 在定义类时,实现 Comparble 接口即可,然后在类 中重写 compareTo 方法。

 

public class Card implements Comparable < Card > { public int rank ; // 数值 public String suit ; // 花色 public Card ( int rank , String suit ) { this . rank = rank ; this . suit = suit ; } // 根据数值比较,不管花色 // 这里我们认为 null 是最小的 @Override

 

public int compareTo ( Card o ) { if ( o == null ) { return 1 ; } return rank - o . rank ; } public static void main ( String [] args ){ Card p = new Card ( 1 , "♠" ); Card q = new Card ( 2 , "♠" ); Card o = new Card ( 1 , "♠" ); System . out . println ( p . compareTo ( o )); // == 0 ,表示牌相等 System . out . println ( p . compareTo ( q )); // < 0 ,表示 p 比较小 System . out . println ( q . compareTo ( p )); // > 0 ,表示 q 比较大 } }

 Compareble是java.lang中的接口类,可以直接使用。

3 基于比较器的比较 

按照比较器方式进行比较,具体步骤如下:
用户自定义比较器类,实现 Comparator接口 public interface Comparator < T > { // 返回值 : // < 0: 表示 o1 指向的对象小于 o2 指向的对象 // == 0: 表示 o1 指向的对象等于 o2 指向的对象 // > 0: 表示 o1 指向的对象等于 o2 指向的对象 int compare ( T o1 , T o2 ); }

 

注意: 区分 Comparable Comparator覆写 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 > { // 根据数值比较,不管花色 // 这里我们认为 null 是最小的

 

@Override public int compare ( Card o1 , Card o2 ) { if ( o1 == o2 ) { return 0 ; } if ( o1 == null ) { return - 1 ; } if ( o2 == null ) { return 1 ; } return o1 . rank - o2 . rank ; } public static void main ( String [] args ){ Card p = new Card ( 1 , "♠" ); Card q = new Card ( 2 , "♠" ); Card o = new Card ( 1 , "♠" ); // 定义比较器对象 CardComparator cmptor = new CardComparator (); // 使用比较器对象进行比较 System . out . println ( cmptor . compare ( p , o )); // == 0 ,表示牌相等 System . out . println ( cmptor . compare ( p , q )); // < 0 ,表示 p 比较小 System . out . println ( cmptor . compare ( q , p )); // > 0 ,表示 q 比较大 } }

 四 小结

三种方式的对比
覆写的方法                                            说明
Object.equals 因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与 否
Comparable.compareTo 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于 内部顺序
Comparator.compare 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性 强

更新不易,希望大家多多支持,如有不当之处,不吝赐教!!!!!

标签:废话,java,rank,比较,不说,suit,println,public,Card
来源: https://blog.csdn.net/qq_60202930/article/details/120377017

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有