Java教程

不说废话之java对象的比较

本文主要是介绍不说废话之java对象的比较,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

目录

一:为何要比较

二:元素的比较

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对象的比较的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!