不说废话之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 比较大
}
}

 Compareblejava.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
需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性

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

  • 31
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 19
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 19
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

爱敲代码的小高

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值