比较相等:
- :比较的是对象的身份(引用中存的地址是不是相同==)
- equals:默认也是调用 == 来比较身份,可以手动重写equals方法按自定义规则进行比较。
PS:
在自定义equals方法时必须注意:
- 判断obj是否为null
- 判断obj是否与this为同一对象
- 判断obj是否可以强制转换
- 对obj进行强制转换,写自定义规则
实现:
class Card implements Comparable<Card> {
//定义一个牌的数据结构
public String rank;
public String shit;
public Card(String rank, String shit) {
this.rank = rank;
this.shit = shit;
}
@Override
public boolean equals(Object obj) {
//第一步判断obj是否为空
if(obj == null) {
return false;
}
//第二步判断obj与this是否引用同一个对象
if(obj == this) {
return true;
}
//第三步判断obj是否可以强转为this类型
if(!(obj instanceof Card)) {
return false;
}
//第四步将obj强转为this类型,自定义判断相等
Card o = (Card) obj;
//按照数字大小进行比较
int thisRank = rankToInt(this.rank);
int oRank = rankToInt(o.rank);
return thisRank == oRank;
}
public int rankToInt(String rank) {
//将面值转为int型
if("A".equals(rank)) {
return 1;
}
if("J".equals(rank)) {
return 11;
}
if("Q".equals(rank)) {
return 12;
}
if("K".equals(rank)) {
return 13;
}
return Integer.parseInt(rank);
}
这样当我们进行== 与equals 判断相等的时候就会发生改变:
Card card = new Card("10", "♥");
Card card1 = new Card("A","♠");
Card card4 = new Card("A", "♣");
//直接等号比较
System.out.println(card == card4);
//
Card card3 = card;
System.out.println(card == card3);
//进行equals比较,
System.out.println(card.equals(card1));
System.out.println(card.equals(card3));
System.out.println(card1.equals(card4));
结果:
false
true
false
true
true
认识认识Comparable:
代码格式:
public interface Comparable<E> {
// 返回值:
// < 0: 表示 this 指向的对象小于 o 指向的对象
// == 0: 表示 this 指向的对象等于 o 指向的对象
// > 0: 表示 this 指向的对象等于 o 指向的对象
int compareTo(E o);
}
实例:
class Card implements Comparable<Card> {
//定义一个牌的数据结构
public String rank;
public String shit;
public Card(String rank, String shit) {
this.rank = rank;
this.shit = shit;
}
@Override
public boolean equals(Object obj) {
//第一步判断obj是否为空
if(obj == null) {
return false;
}
//第二步判断obj与this是否引用同一个对象
if(obj == this) {
return true;
}
//第三步判断obj是否可以强转为this类型
if(!(obj instanceof Card)) {
return false;
}
//第四步将obj强转为this类型,自定义判断相等
Card o = (Card) obj;
//按照数字大小进行比较
int thisRank = rankToInt(this.rank);
int oRank = rankToInt(o.rank);
return thisRank == oRank;
}
public int rankToInt(String rank) {
//将面值转为int型
if("A".equals(rank)) {
return 1;
}
if("J".equals(rank)) {
return 11;
}
if("Q".equals(rank)) {
return 12;
}
if("K".equals(rank)) {
return 13;
}
return Integer.parseInt(rank);
}
@Override
public int compareTo(Card o) {
//将this与o的面值进行转换成int型,然后进行比较
int thisRank = rankToInt(this.rank);
int oRank = rankToInt(o.rank);
//如果要升序就是thisRank - oRank,降序就是反之
return thisRank - oRank;
}
@Override
public String toString() {
return "Card{" +
"rank='" + rank + '\'' +
", shit='" + shit + '\'' +
'}';
}
}
测试:
Card card = new Card("10", "♥");
Card card1 = new Card("A","♠");
Card card2 = new Card("K", "♣");
Card card4 = new Card("A", "♣");
List<Card> list = new ArrayList<>();
list.add(card);
list.add(card1);
list.add(card2);
list.add(card4);
//集合类的排序方法
System.out.println(list);
Collections.sort(list);
System.out.println(list);
结果:
[Card{rank='10', shit='♥'}, Card{rank='A', shit='♠'}, Card{rank='K', shit='♣'}, Card{rank='A', shit='♣'}]
[Card{rank='A', shit='♠'}, Card{rank='A', shit='♣'}, Card{rank='10', shit='♥'}, Card{rank='K', shit='♣'}]
认识Comparator:
代码格式:
public interface Comparator<T> {
// 返回值:
// < 0: 表示 o1 指向的对象小于 o2 指向的对象
// == 0: 表示 o1 指向的对象等于 o2 指向的对象
// > 0: 表示 o1 指向的对象等于 o2 指向的对象
int compare(T o1, T o2); }
实例:
//定义一个匿名内部类就行判断大小
Collections.sort(list, new Comparator<Card>() {
@Override
public int compare(Card o1, Card o2) {
int o1Rank = o1.rankToInt(o1.rank);
int o2Rank = o2.rankToInt(o2.rank);
return o1Rank - o2Rank;
}
});
测试:
[Card{rank='10', shit='♥'}, Card{rank='A', shit='♠'}, Card{rank='K', shit='♣'}, Card{rank='A', shit='♣'}]
[Card{rank='A', shit='♠'}, Card{rank='A', shit='♣'}, Card{rank='10', shit='♥'}, Card{rank='K', shit='♣'}]
差异:
-
重写equals
因为所有类都是继承自object类型,所以自己重写即可,不过只能判断是否相等。 -
重写compareTo
需要手动实现接口,侵入性强,一旦实现,每次用该类都有此顺序,属于内部顺序,而且一个比较对象,只能实现一种比较规则,而且比较的是库的类或者不是自己写的类就难以实现比较。 -
重写compare
需要实现一个比较器对象,对比较类的侵入性低,可以对一个比较的类实现多种比较方法,比Comparable适用范围更加广泛。
与集合框架的配合:
- 使用 contains 类似的方法,内部基本在调用元素的 equals 方法,所以要求元素覆写过 equals 方法
- 使用 HashMap,key 的比较内部会调用 equals 方法,所以要求元素覆写过 equals 方法
- 使用排序相关方法,内部需要进行比较,所以或者选择实现 Comparable 或者传入一个 Comparator
- 使用 TreeMap,key 需要进行大小比较,所以或者选择实现 Comparable 或者传入一个 Comparator
- 其他规则以此类推