Java中的比较
什么是比较?
在计算机领域中,比较分为两种:
身份的比较
值的比较
而在Java中主要有**三种比较方式:**
Object.equals
Comparable
Comparator
比较相等
== 和 equals
1) == :比较对象身份,比较的是两个引用中保存的地址的值(判断引用中存的地址是不是相同)
p == q 表示的是 p 和 q 两个引用指向同一个对象
2) equals:
p.equals(q) 表示 p 指向的对象和 q 指向的对象是否是值语义(被赋予的值)相等的,我们平时比较String类型的时候其实也是进行了重写,是利用Comparable接口。
public class Card {
public int rank; // 数值
public String suit; // 花色
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
public static void main(String[] args) {
Card card1 = new Card(1,"♥");
Card card2 = new Card(1,"♥");
Card o = card1;
System.out.println(card1 == o); //true
System.out.println(card1 == card2); //false
System.out.println(card1.equals(o)); //true
System.out.println(card1.equals(card2)); //false
}
}
equals会默认调用==来比较身份,所以我们在使用的时候可以手动重写equals实现按自定义规则比较
重写注意:
a)this 和 o 是不是相同身份
b)o 是不是为空(null)
c)o 和 this 是不是相同类型
d)对 o 进行强制类型转换
e)按照自定义规则比较
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;
}
if(o == null || !(o instanceof Card)){
return false;
}
Card card = (Card)o;
return rank == card.rank
&& suit.equals(card.suit);
}
public static void main(String[] args) {
Card card1 = new Card(1,"♥");
Card card2 = new Card(1,"♥");
Card o = card1;
System.out.println(card1 == o); //true
System.out.println(card1 == card2); //false
System.out.println(card1.equals(o)); //true
System.out.println(card1.equals(card2)); //true
}
}
比较不等
Javaz中不支持运算符重载,Java中的 < > <= >= 只能针对数字类型来使用,如果创建了两个对象来进行比较大小,就需要专门的方法来完成。
1)实现Comparable接口
重写compareTo方法:this 和 o之间的比较
public class Card implements Comparable<Card> {
public String rank; // 数值
public String suit; // 花色
public Card(String rank, String suit) {
this.rank = rank;
this.suit = suit;
}
@Override
public int compareTo(Card o) {
//对this 和 o 进行比较
//如果this < o ,返回 < 0
//如果this > o ,返回 > 0
//如果this 和 o 相等 ,返回 0
//定义比较规则:扑克牌的点数进行比较
int rank1 = this.convertRank();
int rank2 = o.convertRank();
return rank1 - rank2;
}
private int convertRank(){
//把String类型的rank转成int值
//2-10 =》2-10
//J-A => 11-14
if("A".equals(rank)){
return 14;
}
if("K".equals(rank)){
return 13;
}
if("Q".equals(rank)){
return 12;
}
if("J".equals(rank)){
return 11;
}
return Integer.parseInt(rank);
}
public static void main(String[] args) {
Card card1 = new Card("1","♥");
Card card2 = new Card("1","♥");
Card card3 = new Card("A","♥");
Card o = card1;
System.out.println(card1.compareTo(card2)); // 0
System.out.println(card1.compareTo(card3)); // -13 A定义为数字14 // 1-14=-13
}
}
实例
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Card implements Comparable<Card> {
public String rank; // 数值
public String suit; // 花色
public Card(String rank, String suit) {
this.rank = rank;
this.suit = suit;
}
@Override
public int compareTo(Card o) {
//对this 和 o 进行比较
//如果this < o ,返回 < 0
//如果this > o ,返回 > 0
//如果this 和 o 相等 ,返回 0
//定义比较规则:扑克牌的点数进行比较
int rank1 = this.convertRank();
int rank2 = o.convertRank();
return rank1 - rank2;//升序
//return rank2 - rank1;//降序
}
private int convertRank(){
//把String类型的rank转成int值
//2-10 =》2-10
//J-A => 11-14
if("A".equals(rank)){
return 14;
}
if("K".equals(rank)){
return 13;
}
if("Q".equals(rank)){
return 12;
}
if("J".equals(rank)){
return 11;
}
return Integer.parseInt(rank);
}
@Override
public String toString() {
return "Card{" +
"rank='" + rank + '\'' +
", suit='" + suit + '\'' +
'}';
}
public static void main(String[] args) {
Card card1 = new Card("1","♥");
Card card2 = new Card("1","♥");
Card card3 = new Card("A","♥");
Card o = card1;
System.out.println(card1.compareTo(card2)); // 0
System.out.println(card1.compareTo(card3)); // -13 A定义为数字14 // 1-14=-13
List<Card> cardList = new ArrayList<>();
cardList.add(new Card("A","♥"));
cardList.add(new Card("K","♥"));
cardList.add(new Card("2","♥"));
cardList.add(new Card("J","♥"));
cardList.add(new Card("10","♥"));
Collections.sort(cardList);
System.out.println(cardList);
}
}
结果:
0
-13
[Card{rank='2', suit='♥'},
Card{rank='10', suit='♥'},
Card{rank='J', suit='♥'},
Card{rank='K', suit='♥'},
Card{rank='A', suit='♥'}]
2)实现Comparator比较器
重写compare方法
实例
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Card {
public String rank; // 数值
public String suit; // 花色
public Card(String rank, String suit) {
this.rank = rank;
this.suit = suit;
}
public int convertRank(){
//把String类型的rank转成int值
//2-10 =》2-10
//J-A => 11-14
if("A".equals(rank)){
return 14;
}
if("K".equals(rank)){
return 13;
}
if("Q".equals(rank)){
return 12;
}
if("J".equals(rank)){
return 11;
}
return Integer.parseInt(rank);
}
@Override
public String toString() {
return "Card{" +
"rank='" + rank + '\'' +
", suit='" + suit + '\'' +
'}';
}
}
class CardComparator implements Comparator<Card> {
@Override
public int compare(Card o1, Card o2) {
int rank1 = o1.convertRank();
int rank2 = o2.convertRank();
return rank1 - rank2;//根据数值升序
//return rank2 - rank1;//根据数值降序
}
public static void main(String[] args) {
List<Card> cardList = new ArrayList<>();
cardList.add(new Card("A","♥"));
cardList.add(new Card("K","♥"));
cardList.add(new Card("2","♥"));
cardList.add(new Card("J","♥"));
cardList.add(new Card("10","♥"));
Collections.sort(cardList,new CardComparator());
System.out.println(cardList);
}
}
结果:
[Card{rank='2', suit='♥'},
Card{rank='10', suit='♥'},
Card{rank='J', suit='♥'},
Card{rank='K', suit='♥'},
Card{rank='A', suit='♥'}]
3) Arrays.sort( )(拓展)
可以给Arrays.sort( )的第二个参数,传入排序的比较器,然后来规定排序方式
实例
import java.util.Arrays;
import java.util.Comparator;
public class Card {
public String rank; // 数值
public String suit; // 花色
public Card(String rank, String suit) {
this.rank = rank;
this.suit = suit;
}
public int convertRank() {
//把String类型的rank转成int值
//2-10 =》2-10
//J-A => 11-14
if ("A".equals(rank)) {
return 14;
}
if ("K".equals(rank)) {
return 13;
}
if ("Q".equals(rank)) {
return 12;
}
if ("J".equals(rank)) {
return 11;
}
return Integer.parseInt(rank);
}
@Override
public String toString() {
return "Card{" +
"rank='" + rank + '\'' +
", suit='" + suit + '\'' +
'}';
}
}
class CardComparator implements Comparator<Card> {
@Override
public int compare(Card o1, Card o2) {
int rank1 = o1.convertRank();
int rank2 = o2.convertRank();
return rank1 - rank2;//根据数值升序
//return rank2 - rank1;//根据数值降序
}
public static void main(String[] args) {
Card[] cards = new Card[3];
cards[0] = new Card("A","♥");
cards[1] = new Card("2","♥");
cards[2] = new Card("J","♥");
CardComparator cardComparator = new CardComparator();
Arrays.sort(cards,cardComparator);
System.out.println(Arrays.toString(cards));
}
}
结果:
[Card{rank='2', suit='♥'}, Card{rank='J', suit='♥'}, Card{rank='A', suit='♥'}]
三种比较方法的比较
覆写的方法 | 说明 |
---|---|
Object.equals | 因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否 |
Comparable.compareTo | 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序 |
Comparator.compare | 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强 |
和Java集合框架的配合
1、使用 contains 类似的方法,内部基本在调用元素的 equals 方法,所以要求元素重写过 equals 方法
2、使用 HashMap,key 的比较内部会调用 equals 方法,所以要求元素重写过 equals 方法
3、使用排序相关方法,内部需要进行比较,所以或者选择实现Comparable 或者传入一个 Comparator
4、使用 TreeMap,key 需要进行大小比较,所以或者选择实现 Comparable 或者传入一个 Comparator