java对象对比之comparable和comparator的区别

网友投稿 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小时内删除侵权内容。

上一篇:尽管存在 DDoS 攻击,但不要放弃 Dyn 或 DNS 服务提供商
下一篇:一款真正可以操作的数据中心可视化管理软件
相关文章

 发表评论

暂时没有评论,来抢沙发吧~