为什么枚举要实现接口?
238
2022-10-18
java对象对比之comparable和comparator的区别
一、元素的比较
1.1 基本类型的比较
java中的基本类型的对象是可以进行比较的
如
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
char c1 = 'A';
char c2 = 'B';
System.out.println(c1>c2);
System.out.println(c1==c2);
System.out.println(c1 boolean b1 = true; boolean b2 =false; System.out.println(b1==b2); System.out.println(b1!=b2); } 1.2 对象的比较 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==c3); // System.out.println(c1>c2); 编译报错 // System.out.println(c1 } } class Card{ public int rank; public String suit; public Card(int rank,String suit){ this.rank = rank; this.suit = suit; } } 可以看出在进行相等比较时,是可以进行比较的,但进行大于或小于比较就不行了 这是因为对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意。 二、对象的比较 有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整堆,那该如何处理呢? 2.1 覆写基类的equal 一般覆写 equals 的套路就是上面演示的 1.如果指向同一个对象,返回 true 2.如果传入的为 null,返回 false 3.如果传入的对象类型不是 Card,返回 false 4.按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌 5.注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较 覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。 2.2 基于Comparable接口的比较 Comparble是JDK提供的泛型的比较接口类,源码实现具体如下: public interface Comparable /** * Compares this object with the specified object for order. Returns a * negative integer, zero, or a positive integer as this object is less * than, equal to, or greater than the specified object. * * The implementor must ensure sgn(x.compareTo(y)) == * -sgn(y.compareTo(x)) for all x and y. (This * implies that x.compareTo(y) must throw an exception iff * y.compareTo(x) throws an exception.) * * The implementor must also ensure that the relation is transitive: * (x.compareTo(y)>0 && y.compareTo(z)>0) implies * x.compareTo(z)>0. * * Finally, the implementor must ensure that x.compareTo(y)==0 * implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for * all z. * * It is strongly recommended, but not strictly required that * (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any * class that implements the Comparable interface and violates * this condition should clearly indicate this fact. The recommended * language is "Note: this class has a natural ordering that is * inconsistent with equals." * * In the foregoing description, the notation * sgn(expression) designates the mathematical * signum function, which is defined to return one of -1, * 0, or 1 according to whether the value of * expression is negative, zero or positive. * * @param o the object to be compared. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. * * @throws NullPointerException if the specified object is null * @throws ClassCastException if the specified object's type prevents it * from being compared to this object. */ public int compareTo(T o); } 可以看到在Comparable接口中只实现了一个方法 compareTo,因此我们在实现自定义比较时,在类的定义中实现Comparable接口即可,然后在类中重写compareTo方法 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.compareTo(c2)); System.out.println(c1.compareTo(c3)); System.out.println(c2.compareTo(c3)); } } class Card implements Comparable 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 rank-o.rank; } } 当前值比要比较值小则输出-1;当前值与要比较值相等则输出0; 当前值比要比较值大输出1; 2.3 基于比较器Comparator的比较 首先了解一下Comparator接口 public interface Comparator /** * Compares its two arguments for order. Returns a negative integer, * zero, or a positive integer as the first argument is less than, equal * to, or greater than the second. * * In the foregoing description, the notation * sgn(expression) designates the mathematical * signum function, which is defined to return one of -1, * 0, or 1 according to whether the value of * expression is negative, zero or positive. * * The implementor must ensure that sgn(compare(x, y)) == * -sgn(compare(y, x)) for all and y. (This * implies that compare(x, y) must throw an exception if and only * if compare(y, x) throws an exception.) * * The implementor must also ensure that the relation is transitive: * <tt>((compare(x, y)>0) && (compare(y, z)>0)) implies * compare(x, z)>0. * * Finally, the implementor must ensure that compare(x, y)==0 * implies that sgn(compare(x, z))==sgn(compare(y, z)) for all * z. * * It is generally the case, but not strictly required that * (compare(x, y)http://==0) == (x.equals(y)). Generally speaking, * any comparator that violates this condition should clearly indicate * this fact. The recommended language is "Note: this comparator * imposes orderings that are inconsistent with equals." * * @param o1 the first object to be compared. * @param o2 the second object to be compared. * @return a negative integer, zero, or a positive integer as the * first argument is less than, equal to, or greater than the * second. * @throws NullPointerException if an argument is null and this * comparator does not permit null arguments * @throws ClassCastException if the arguments' types prevent them from * being compared by this comparator. */ int compare(T o1, T o2); 当然还有许多comparator实现的自定义比较方法,但这里我只贴出需要自己实现的方法compare; 接下来看看comparator的用法 当使用comparator时,如果要使用自定义的比较方式需要实现comparator接口,并且覆写compare方法;因此需要自己构造一个比较器类实现comparator接口,然后利用我们自定义的比较器进行比较即可; 下面是一个应用实例 // write your code here import java.util.*; import java.lang.*; public class Main{ public static void main(String[] args){ Card c1 = new Card(1,"♠"); Card c2 = new Card(2,"♠"); Card c3 = c1; CardComparator cardComparator = new CardComparator(); System.out.println(cardComparator.compare(c1,c2)); System.out.println(cardComparator.compare(c1,c3)); System.out.println(cardComparator.compare(c2,c3)); } } class Card { public int rank; public String suit; public Card(int rank,String suit){ this.rank = rank; this.suit = suit; } } class CardComparator implements Comparator @Override public int compare(Card o1, Card o2) { if (o1==o2){ return 0; } if (o1==null)return -1; if (o2==null)return 1; return o1.rank-o2.rank; } } Comparator属于java.util包中泛型接口类,使用时必须导入相关的包; 我们将Comparator中的compare方法重写,就可以对需要进行对比的对象进行对比并返回结果。 2.4 几种不同的compare对比 方法 说明 object.equals 直接覆写即可,不过只能比较相等与否 Comparable.compareTO 需要手动实现接口,当前类之后的所有对比方式都被定义,属于内部顺序 Comparator.compare 需要实现一个比较器对象,对待比较类的侵入性弱,但对代码的侵入性强
boolean b1 = true;
boolean b2 =false;
System.out.println(b1==b2);
System.out.println(b1!=b2);
}
1.2 对象的比较
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==c3);
// System.out.println(c1>c2); 编译报错
// System.out.println(c1 } } class Card{ public int rank; public String suit; public Card(int rank,String suit){ this.rank = rank; this.suit = suit; } } 可以看出在进行相等比较时,是可以进行比较的,但进行大于或小于比较就不行了 这是因为对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意。 二、对象的比较 有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整堆,那该如何处理呢? 2.1 覆写基类的equal 一般覆写 equals 的套路就是上面演示的 1.如果指向同一个对象,返回 true 2.如果传入的为 null,返回 false 3.如果传入的对象类型不是 Card,返回 false 4.按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌 5.注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较 覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。 2.2 基于Comparable接口的比较 Comparble是JDK提供的泛型的比较接口类,源码实现具体如下: public interface Comparable /** * Compares this object with the specified object for order. Returns a * negative integer, zero, or a positive integer as this object is less * than, equal to, or greater than the specified object. * * The implementor must ensure sgn(x.compareTo(y)) == * -sgn(y.compareTo(x)) for all x and y. (This * implies that x.compareTo(y) must throw an exception iff * y.compareTo(x) throws an exception.) * * The implementor must also ensure that the relation is transitive: * (x.compareTo(y)>0 && y.compareTo(z)>0) implies * x.compareTo(z)>0. * * Finally, the implementor must ensure that x.compareTo(y)==0 * implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for * all z. * * It is strongly recommended, but not strictly required that * (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any * class that implements the Comparable interface and violates * this condition should clearly indicate this fact. The recommended * language is "Note: this class has a natural ordering that is * inconsistent with equals." * * In the foregoing description, the notation * sgn(expression) designates the mathematical * signum function, which is defined to return one of -1, * 0, or 1 according to whether the value of * expression is negative, zero or positive. * * @param o the object to be compared. * @return a negative integer, zero, or a positive integer as this object * is less than, equal to, or greater than the specified object. * * @throws NullPointerException if the specified object is null * @throws ClassCastException if the specified object's type prevents it * from being compared to this object. */ public int compareTo(T o); } 可以看到在Comparable接口中只实现了一个方法 compareTo,因此我们在实现自定义比较时,在类的定义中实现Comparable接口即可,然后在类中重写compareTo方法 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.compareTo(c2)); System.out.println(c1.compareTo(c3)); System.out.println(c2.compareTo(c3)); } } class Card implements Comparable 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 rank-o.rank; } } 当前值比要比较值小则输出-1;当前值与要比较值相等则输出0; 当前值比要比较值大输出1; 2.3 基于比较器Comparator的比较 首先了解一下Comparator接口 public interface Comparator /** * Compares its two arguments for order. Returns a negative integer, * zero, or a positive integer as the first argument is less than, equal * to, or greater than the second. * * In the foregoing description, the notation * sgn(expression) designates the mathematical * signum function, which is defined to return one of -1, * 0, or 1 according to whether the value of * expression is negative, zero or positive. * * The implementor must ensure that sgn(compare(x, y)) == * -sgn(compare(y, x)) for all and y. (This * implies that compare(x, y) must throw an exception if and only * if compare(y, x) throws an exception.) * * The implementor must also ensure that the relation is transitive: * <tt>((compare(x, y)>0) && (compare(y, z)>0)) implies * compare(x, z)>0. * * Finally, the implementor must ensure that compare(x, y)==0 * implies that sgn(compare(x, z))==sgn(compare(y, z)) for all * z. * * It is generally the case, but not strictly required that * (compare(x, y)http://==0) == (x.equals(y)). Generally speaking, * any comparator that violates this condition should clearly indicate * this fact. The recommended language is "Note: this comparator * imposes orderings that are inconsistent with equals." * * @param o1 the first object to be compared. * @param o2 the second object to be compared. * @return a negative integer, zero, or a positive integer as the * first argument is less than, equal to, or greater than the * second. * @throws NullPointerException if an argument is null and this * comparator does not permit null arguments * @throws ClassCastException if the arguments' types prevent them from * being compared by this comparator. */ int compare(T o1, T o2); 当然还有许多comparator实现的自定义比较方法,但这里我只贴出需要自己实现的方法compare; 接下来看看comparator的用法 当使用comparator时,如果要使用自定义的比较方式需要实现comparator接口,并且覆写compare方法;因此需要自己构造一个比较器类实现comparator接口,然后利用我们自定义的比较器进行比较即可; 下面是一个应用实例 // write your code here import java.util.*; import java.lang.*; public class Main{ public static void main(String[] args){ Card c1 = new Card(1,"♠"); Card c2 = new Card(2,"♠"); Card c3 = c1; CardComparator cardComparator = new CardComparator(); System.out.println(cardComparator.compare(c1,c2)); System.out.println(cardComparator.compare(c1,c3)); System.out.println(cardComparator.compare(c2,c3)); } } class Card { public int rank; public String suit; public Card(int rank,String suit){ this.rank = rank; this.suit = suit; } } class CardComparator implements Comparator @Override public int compare(Card o1, Card o2) { if (o1==o2){ return 0; } if (o1==null)return -1; if (o2==null)return 1; return o1.rank-o2.rank; } } Comparator属于java.util包中泛型接口类,使用时必须导入相关的包; 我们将Comparator中的compare方法重写,就可以对需要进行对比的对象进行对比并返回结果。 2.4 几种不同的compare对比 方法 说明 object.equals 直接覆写即可,不过只能比较相等与否 Comparable.compareTO 需要手动实现接口,当前类之后的所有对比方式都被定义,属于内部顺序 Comparator.compare 需要实现一个比较器对象,对待比较类的侵入性弱,但对代码的侵入性强
}
}
class Card{
public int rank;
public String suit;
public Card(int rank,String suit){
this.rank = rank;
this.suit = suit;
}
}
可以看出在进行相等比较时,是可以进行比较的,但进行大于或小于比较就不行了
这是因为对于用户实现自定义类型,都默认继承自Object类,而Object类中提供了equal方法,而==默认情况下调用的就是equal方法,但是该方法的比较规则是:没有比较引用变量引用对象的内容,而是直接比较引用变量的地址,但有些情况下该种比较就不符合题意。
二、对象的比较
有些情况下,需要比较的是对象中的内容,比如:向优先级队列中插入某个对象时,需要对按照对象中内容来调整堆,那该如何处理呢?
2.1 覆写基类的equal
一般覆写 equals 的套路就是上面演示的
1.如果指向同一个对象,返回 true
2.如果传入的为 null,返回 false
3.如果传入的对象类型不是 Card,返回 false
4.按照类的实现目标完成比较,例如这里只要花色和数值一样,就认为是相同的牌
5.注意下调用其他引用类型的比较也需要 equals,例如这里的 suit 的比较
覆写基类equal的方式虽然可以比较,但缺陷是:equal只能按照相等进行比较,不能按照大于、小于的方式进行比较。
2.2 基于Comparable接口的比较
Comparble是JDK提供的泛型的比较接口类,源码实现具体如下:
public interface Comparable
/**
* Compares this object with the specified object for order. Returns a
* negative integer, zero, or a positive integer as this object is less
* than, equal to, or greater than the specified object.
*
*
The implementor must ensure sgn(x.compareTo(y)) ==
* -sgn(y.compareTo(x)) for all x and y. (This
* implies that x.compareTo(y) must throw an exception iff
* y.compareTo(x) throws an exception.)
*
*
The implementor must also ensure that the relation is transitive:
* (x.compareTo(y)>0 && y.compareTo(z)>0) implies
* x.compareTo(z)>0.
*
*
Finally, the implementor must ensure that x.compareTo(y)==0
* implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for
* all z.
*
*
It is strongly recommended, but not strictly required that
* (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any
* class that implements the Comparable interface and violates
* this condition should clearly indicate this fact. The recommended
* language is "Note: this class has a natural ordering that is
* inconsistent with equals."
*
*
In the foregoing description, the notation
* sgn(expression) designates the mathematical
* signum function, which is defined to return one of -1,
* 0, or 1 according to whether the value of
* expression is negative, zero or positive.
*
* @param o the object to be compared.
* @return a negative integer, zero, or a positive integer as this object
* is less than, equal to, or greater than the specified object.
*
* @throws NullPointerException if the specified object is null
* @throws ClassCastException if the specified object's type prevents it
* from being compared to this object.
*/
public int compareTo(T o);
}
可以看到在Comparable接口中只实现了一个方法 compareTo,因此我们在实现自定义比较时,在类的定义中实现Comparable接口即可,然后在类中重写compareTo方法
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.compareTo(c2));
System.out.println(c1.compareTo(c3));
System.out.println(c2.compareTo(c3));
}
}
class Card implements Comparable
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 rank-o.rank;
}
}
当前值比要比较值小则输出-1;当前值与要比较值相等则输出0;
当前值比要比较值大输出1;
2.3 基于比较器Comparator的比较
首先了解一下Comparator接口
public interface Comparator
/**
* Compares its two arguments for order. Returns a negative integer,
* zero, or a positive integer as the first argument is less than, equal
* to, or greater than the second.
*
* In the foregoing description, the notation
* sgn(expression) designates the mathematical
* signum function, which is defined to return one of -1,
* 0, or 1 according to whether the value of
* expression is negative, zero or positive.
*
* The implementor must ensure that sgn(compare(x, y)) ==
* -sgn(compare(y, x)) for all and y. (This
* implies that compare(x, y) must throw an exception if and only
* if compare(y, x) throws an exception.)
*
* The implementor must also ensure that the relation is transitive:
* <tt>((compare(x, y)>0) && (compare(y, z)>0)) implies
* compare(x, z)>0.
*
* Finally, the implementor must ensure that compare(x, y)==0
* implies that sgn(compare(x, z))==sgn(compare(y, z)) for all
* z.
*
* It is generally the case, but not strictly required that
* (compare(x, y)http://==0) == (x.equals(y)). Generally speaking,
* any comparator that violates this condition should clearly indicate
* this fact. The recommended language is "Note: this comparator
* imposes orderings that are inconsistent with equals."
*
* @param o1 the first object to be compared.
* @param o2 the second object to be compared.
* @return a negative integer, zero, or a positive integer as the
* first argument is less than, equal to, or greater than the
* second.
* @throws NullPointerException if an argument is null and this
* comparator does not permit null arguments
* @throws ClassCastException if the arguments' types prevent them from
* being compared by this comparator.
*/
int compare(T o1, T o2);
当然还有许多comparator实现的自定义比较方法,但这里我只贴出需要自己实现的方法compare;
接下来看看comparator的用法
当使用comparator时,如果要使用自定义的比较方式需要实现comparator接口,并且覆写compare方法;因此需要自己构造一个比较器类实现comparator接口,然后利用我们自定义的比较器进行比较即可;
下面是一个应用实例
// write your code here
import java.util.*;
import java.lang.*;
public class Main{
public static void main(String[] args){
Card c1 = new Card(1,"♠");
Card c2 = new Card(2,"♠");
Card c3 = c1;
CardComparator cardComparator = new CardComparator();
System.out.println(cardComparator.compare(c1,c2));
System.out.println(cardComparator.compare(c1,c3));
System.out.println(cardComparator.compare(c2,c3));
}
}
class Card {
public int rank;
public String suit;
public Card(int rank,String suit){
this.rank = rank;
this.suit = suit;
}
}
class CardComparator implements Comparator
@Override
public int compare(Card o1, Card o2) {
if (o1==o2){
return 0;
}
if (o1==null)return -1;
if (o2==null)return 1;
return o1.rank-o2.rank;
}
}
Comparator属于java.util包中泛型接口类,使用时必须导入相关的包;
我们将Comparator中的compare方法重写,就可以对需要进行对比的对象进行对比并返回结果。
2.4 几种不同的compare对比
方法
说明
object.equals
直接覆写即可,不过只能比较相等与否
Comparable.compareTO
需要手动实现接口,当前类之后的所有对比方式都被定义,属于内部顺序
Comparator.compare
需要实现一个比较器对象,对待比较类的侵入性弱,但对代码的侵入性强
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~