java对象比较
文章目录
- java对象比较
- 元素的比较
- 类的比较
- 比较方法
- 重写equals方法
- 基于Comparble接口类的比较
- 基于比较器比较基于比较器比较:Comparator接口
元素的比较
在java中,基本类型的对象可以直接比较大小。
public static void main(String[] args) {int a=12;int b=55;System.out.println(a > b);System.out.println(a == b);System.out.println(a<b);//字符的比较根据字符所对应ASCII值来比较大小char ch1='a';char ch2='b';char ch3='c';System.out.println(ch1>ch2);System.out.println(ch1==ch2);System.out.println(ch1<ch2);boolean b1=true;boolean b2=false;System.out.println(b1==b2);System.out.println(b1!=b2);}
对于String类的比较可以参考我之前写的博客:初识java的String类
类的比较
对于类的比较如果直接像元素比较一样可能会造成编译错误或者与预期效果的不一样。
class Card{public int rank;public String suit;public Card(int rank, String suit) {this.rank = rank;this.suit = suit;}}public class Main{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);//打印false,因为c1和c2指向的是不同对象}}
从此编译结果中我们可以发现,java中引用类型的变量不能直接按照> 或者< 方式进行比较,但确可以使用==符号进行比较?
原因:对于用户自己实现定义的类型,都是默认为Object类,Object类提供了equal方法,此方法的比较规则是:无比较引用变量引用对象的内容,而是直接比较引用变量的地址,因此equal方法一般在使用的时候会被重写
// Object中equal的实现,可以看到:直接比较的是两个引用变量的地址public boolean equals(Object obj) {return (this == obj);}
比较方法
在一些情况下,我们需要比较的是对象的内容,而不是比较对象的地址是否相同,则需要重写比较方法。
重写equals方法
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;// o如果是null对象,或者o不是Card的子类if (o == null || !(o instanceof Card)) return false;Card card = (Card) o;return rank == card.rank && Objects.equals(suit, card.suit);}}Public class Main{public static void main(String[] args){Card c1 = new Card(1, "♠");Card c2 = new Card(1, "♠");System.out.println(c1.equals(c2));}}
其equal方法实现如下:
- 如果这个类指向同一个对象则直接返回true;
- 如果传入的为空或者其对象类型不是Card,则返回false
- 按照类的实现目标完成比较,这里只要花色和数值一样,就认为是相同的牌
- 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较
基于Comparble接口类的比较
Comparble是JDK提供的泛型的比较接口类,源码实现具体如下:
public interface Comparable<E>{// 返回值:// < 0: 表示 this 指向的对象小于 o 指向的对象// == 0: 表示 this 指向的对象等于 o 指向的对象// > 0: 表示 this 指向的对象等于 o 指向的对象public int compareTo(T 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) {return this.rank-o.rank;}@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || !(o instanceof Card)) return false;Card card = (Card) o;return rank == card.rank && Objects.equals(suit, card.suit);}}public class Main {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 比较大}}
基于比较器比较基于比较器比较:Comparator接口
按照比较器方式进行比较,具体步骤如下:
- 户自定义比较器类,实现Comparator接口
- 覆写Comparator中的compare方法
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;if (o == null || !(o instanceof Card)) return false;Card card = (Card) o;return rank == card.rank && Objects.equals(suit, card.suit);}}class CardComparator implements Comparator<Card>{@Override// 返回值:// < 0: 表示 o1 指向的对象小于 o2 指向的对象// == 0: 表示 o1 指向的对象等于 o2 指向的对象// > 0: 表示 o1 指向的对象等于 o2 指向的对象public int compare(Card o1, Card o2) {if (o1 == o2) {return 0;}//判断o1是否为空if (o1 == null) {return -1;}//判断o2是否为空if (o2 == null) {return 1;}return o1.rank - o2.rank;}}public class Main {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();// 使用比较器对象进行比较// == 0,表示牌相等System.out.println(cmptor.compare(p, o));// < 0,表示 p 比较小System.out.println(cmptor.compare(p, q));// > 0,表示 q 比较大System.out.println(cmptor.compare(q, p));}}
三种比较方式的对比
覆写的方法 | 解释说明 |
---|---|
Object.equals | 因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否 |
Comparable.compareTo | 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序 |
Comparator.compare | 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强 |