Java对象的比较
- PriorityQueue中插入对象
- 元素的比较
- 基本数据类型的比较
- 对象的比较
- 重写基类的equals方法
- 基于Comparble接口类的比较
- 基于比较器进行比较
PriorityQueue中插入对象
优先级队列在插入元素时有个要求:插入的元素不能是null或者元素之间必须要能够进行比较,为了简单起见,我们只是插入了Integer类型,那优先级队列中能否插入自定义类型对象呢?
/**
* Card:扑克牌类
* rank:数值
* card:花色
*/
class Card{
public int rank;
public String suit;
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
}
public class test {
public static void main(String[] args) {
PriorityQueue<Card> cards = new PriorityQueue<>();
Card c1 = new Card(9,"♣");
Card c2 = new Card(7,"♦");
cards.offer(c1);
cards.offer(c2);
}
}
我们定义了一个扑克牌类 用一个优先级队列来储存扑克牌类的对象 当我们创建了两个扑克牌对象 然后把两张扑克牌放入优先级队列中
此时我们运行程序
发现程序出现异常
原因就是 在构建优先级队列时 入队的元素都要进行比较 而我们传入的是一个自定义类型 程序并不知道我们要根据什么来比较类的大小 所以在这里出现了异常
元素的比较
基本数据类型的比较
在Java中,基本类型的对象可以直接比较大小。
对象的比较
有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整堆,那该如何处理呢?
重写基类的equals方法
class Card{
public int rank;
public String suit;
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
public boolean equals(Object o){
//自己和自己比较
if(this == o){
return true;
}
//o如果是null对象或者o不是Card的子类
if(o == null || !(o instanceof Card)){
return false;
}
Card c = (Card)o;
return rank == c.rank && suit.equals(c.suit);
}
}
注意: 一般覆写 equals 的套路就是上面演示的
- 如果指向同一个对象,返回 true
- 如果传入的为 null,返回 false
- 如果传入的对象类型不是 Card,返回 false
- 按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌
- 注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较
覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。
即只能比较是否相同 不能比较谁大谁小
基于Comparble接口类的比较
Comparble是JDK提供的泛型的比较接口类,源码实现具体如下:
public interface Comparable<E> {
// 返回值:
// < 0: 表示 this 指向的对象小于 o 指向的对象
// == 0: 表示 this 指向的对象等于 o 指向的对象
// > 0: 表示 this 指向的对象大于 o 指向的对象
int compareTo(E o);
}
对用用户自定义类型,如果要想按照大小与方式进行比较时:在定义类时,实现Comparble接口即可,然后在类中重写compareTo方法。
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 class test {
public static void main(String[] args) {
PriorityQueue<Card> cards = new PriorityQueue<>();
Card c1 = new Card(9,"♣");
Card c2 = new Card(7,"♦");
System.out.println(c1.compareTo(c2));
}
}
我们可以看到程序的返回结果是 2 也就是两张牌的差值 这样就可以判断出两张牌的大小关系
基于比较器进行比较
按照比较器方式进行比较,具体步骤如下:
用户自定义比较器类,实现Comparator接口
覆写Comparator中的compare方法
class CardComparator implements Comparator<Card>{
@Override
public int compare(Card o1, Card o2) {
return o1.rank - o2.rank;
}
}
/**
* Card:扑克牌类
* rank:数值
* card:花色
*/
class Card {
public int rank;
public String suit;
public Card(int rank, String suit) {
this.rank = rank;
this.suit = suit;
}
}
public class test {
public static void main(String[] args) {
PriorityQueue<Card> cards = new PriorityQueue<>();
Card c1 = new Card(9,"♣");
Card c2 = new Card(7,"♦");
CardComparator comparator = new CardComparator();
System.out.println(comparator.compare(c1,c2));
}
}
这种方法好在不需要在类本身中修改比较的方法 类只需要实现接口 就可以完成比较