基本类型的比较
Java中的基本类型可以直接通过比较运算符(>,<,>=,<=,==,!=)进行比较:
public class Test { 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); } }
运行结果如下:
对象的比较
而对于对象来说,使用>和<会报错,使用==比较的是地址(即是不是同一个对象):
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) { 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指向的是同一个对象 } }
运行结果如下:
自定义类型能使用==是因为自定义类型都会默认继承Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是equal方法的较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址:
既然使用比较运算符比较的不是对象的内容,那我们应该怎么比较对象的内容呢?我们可以通过重写equals,comparable接口类和比较器进行比较。
1.重写equals
自定义类型都会默认继承Object类,而Object类中提供了equal方法。
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 obj) { // 如果obj是自己 if (this == obj) { return true; } // o如果是null对象,或者o不是Card的子类 if (obj == null || obj instanceof Card) { return false; } Card o = (Card)obj; //基本类型rank用==比较,引用类型用equals比较 return this.rank == o.rank && suit.equals(obj); } } public class Test { public static void main(String[] args) { Card c1 = new Card(1, "♠"); Card c2 = new Card(2, "♠"); Card c3 = c1; System.out.println(c1.equals(c2)); System.out.println(c1.equals(c3)); } }
运行结果如下:
重写equals方法虽然能比较对象的大小,但返回的是正负,如果想要按照大于小于的方式进行比较需要用到后面两种方法。
2.Comparable接口类
Comparabl e是JDK提供的泛型的比较接口类, 是 java.lang 中的接口类,可以直接使用。CompareTo的 返回值 :1.< 0: 表示 o1 指向的对象小于 o2 指向的对象;2.== 0: 表示 o1 指向的对象等于 o2 指向的对象;3.> 0: 表示 o1 指向的对象等于 o2 指向的对象;对于自定义类型,如果要想按照大小与方式进行比较时,实现 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; } @Override public int compareTo(Card o) { // 没有牌是最小的 if (o == null) { return 1; } // 根据数值比较,不管花色 return this.rank - o.rank; } } public class Test { 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 比较大 } }
运行结果如下:
3.比较器比较
Comparator 是 java.util 包中的泛型接口类,使用时必须导入对应的包。compare返回值 :1. < 0: 表示 o1 指向的对象小于 o2 指向的对象;2. == 0: 表示 o1 指向的对象等于 o2 指向的对象;3. > 0: 表示 o1 指向的对象等于 o2 指向的对象;使用比较器比较需要我们自定义比较器类:实现 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> { @Override public int compare(Card o1, Card o2) { //是自己,返回0 if (o1 == o2) { return 0; } //o2没牌最小,返回-1 if (o1 == null) { return -1; } //自己没牌,返回1 if (o2 == null) { return 1; } //根据数值比较,不管花色 return o1.rank - o2.rank; } } public class Test { public static void main(String[] args){ Card p = new Card(1, "♠"); Card q = new Card(2, "♠"); Card o = new Card(1, "♠"); // 定义比较器对象 CardComparator cardComparator = new CardComparator(); // 使用比较器对象进行比较 System.out.println(cardComparator.compare(p, o)); // == 0,表示牌相等 System.out.println(cardComparator.compare(p, q)); // < 0,表示 p 比较小 System.out.println(cardComparator.compare(q, p)); // > 0,表示 q 比较大 } }
三种方式的比较
重写的方法 描述 Object.equals() 因为所有类都是继承自 Object 的,所以直接覆写即可,不过只能比较相等与否 Comparable.compareTo() 需要手动实现接口,侵入性比较强,但一旦实现,每次用该类都有顺序,属于内部顺序 Comparator.compare() 需要实现一个比较器对象,对待比较类的侵入性弱,但对算法代码实现侵入性强