今天在开发中无意看到Integer包装类内部实现了Comparable接口,因此探查一下该接口作用:
查看API解释:
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的compareTo方法被称为它的自然比较方法。
为什么需要实现这个接口呢?
首先看一下数据的例子:
String[] strArr = {'A','B','C','E','D'};
Arrays.sort(strArr);
for (String string : strArr) {
System.out.print(string+';');
}
输出结果:
A;B;C;D;E;
从中我们可以看出sort方法对数据中的String字符串按照一定规则进行了排序,那为什么会排序呢?
查看String类我们可以看到:
它也实现了Comparable接口。里面实现了compareTo方法,所以按照某种规则能够进行排序。
如果数组中的对象不是String而是自定义的类型呢?
public class ComparableDemo{
public static void main(String[] args) {
Object[] objArray = {new Person(20,'jack'),new Person(17,'tom'),
new Person(27,'aj')};
for (Object object : objArray) {
System.out.print(object.toString());
}
Arrays.sort(objArray);
for (Object object : objArray) {
System.out.print(object.toString());
}
}
}
public class Person {
private Integer age;
private String name;
public Person(int age,String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return 'Person [age=' + age + ', name=' + name + ']';
}
}
结果为:
Person [age=20, name=jack]Person [age=17, name=tom]Person [age=27, name=aj]
Exception in thread 'main' java.lang.ClassCastException: interfacedemo.Person cannot be cast to java.lang.Comparable
at java.util.ComparableTimSort.countRunAndMakeAscending(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.ComparableTimSort.sort(Unknown Source)
at java.util.Arrays.sort(Unknown Source)
at interfacedemo.ComparableDemo.main(ComparableDemo.java:18)
可以看到不进行排序打印是正常的,但是排序时报错了。因为系统无法知道使用什么规则进行排序。
我们存入字符串排序成功是因为String类已经实现Comparable接口,因此想要实现自定义对象比较同样需要实现该接口,其中的比较方法规则由我们自己设定。
接口简介
实现此接口的对象列表可以通过Collections.sort进行自动排序。实现此接口的对象可以用作有序映射中的键或有序集合中的元素,无需指定比较器。
对于类C的每一个e1和e2来说,当且仅当ecompareTo(e==0与eequals(e具有相同的boolean值时,类C的自然排序才叫做与equals一致。注意,null不是任何类的实例,即使equals(nul返回false,compareTo(nul也将抛出NullPointerException。
建议最好使自然排序与equals一致。这是因为在使用自然排序与equals不一致的元素时,没有显式比较器的有序集合行为表现“怪异”。尤其是,这样的有序集合违背了根据equals方法定义的集合的常规协定。
例如,如果将两个键a和b添加到没有使用显式比较器的有序集合中,使(!equals(&&compareTo(==0),那么第二个add操作将返回false,因为从有序集合的角度来看,a和b是相等的。
实际上,所有实现Comparable的Java核心类都具有与equals一致的自然排序。javmatBigDecimal是个例外,它的自然排序将值相等但精确度不同的BigDecimal对象视为相等。
从数学上讲,定义给定类C上自然排序的关系式如下:
{(x, y)|x.compareTo(y) <= 0}。
整体排序的商是:
{(x, y)|x.compareTo(y) == 0}。
它直接遵循compareTo的协定,商是C的等价关系,自然排序是C的整体排序。当说到类的自然排序与equals一致时,是指自然排序的商是由类的equals(Object)方法定义的等价关系。
{(x, y)|x.equals(y)}。
此接口是JavaCollectionsFramework的成员。
实现该接口
上面的例子进行修改,这里通过比较对象中的age属性进行排序
public class Person implements Comparable{
private Integer age;
private String name;
public Person(int age,String name) {
this.age = age;
this.name = name;
}
@Override
public String toString() {
return 'Person [age=' + age + ', name=' + name + ']';
}
//进行方法重写
@Override
public int compareTo(Object o) {
Person p = (Person)o;
return this.age - p.age;
}
}
结果打印:
Person[age=20,name=jack]Person[age=17,name=tom]Person[age=27,name=aj]Person[age=17,name=tom]Person[age=20,name=jack]Person[age=27,name=aj]
最后附上该方法API描述:
比较此对象与指定对象的顺序。如果该对象小于、等于或大于指定对象,则分别返回负整数、零或正整数。
实现类必须确保对于所有的x和y都存在sgn(x.compareTo(y))==-sgn(y.compareTo(x))的关系。
实现类还必须确保关系是可传递的:(x.compareTo(y)>0&&y.compareTo(z)>0)意味着x.compareTo(z)>0。
实现者必须确保x.compareTo(y)==0意味着对于所有的z,都存在sgn(x.compareTo(z))==sgn(y.compareTo(z))。强烈推荐(x.compareTo(y)==0)==(x.equals(y))这种做法,但并不是严格要求这样做。一般来说,任何实现Comparable接口和违背此条件的类都应该清楚地指出这一事实。推荐如此阐述:“注意:此类具有与equals不一致的自然排序。”
在前面的描述中,符号sgn(expressio指定signum数学函数,该函数根据expression的值是负数、零还是正数,分别返回-0或1中的一个值。
参数:
o-要比较的对象。
返回:
负整数、零或正整数,根据此对象是小于、等于还是大于指定对象。
抛出:
ClassCastException-如果指定对象的类型不允许它与此对象进行比较。
文章为作者独立观点,不代表 股票程序化软件自动交易接口观点
富途证券量化接口2022-11-30
看没看内容,就看了集采这两字吧。哈哈哈哈。这集采是21年的,集采合同2年,这不快到期了,国家也没出台文件规定到期后怎么弄,是否接续。现在是国家组织接续,但有一点,接续工作是没集采文件的,这就和文件的集采是有区别的,相比是放宽了。今年报量的医疗机构增加了1000多家,也就买的人增加了。增量了。但不影响明天跌,因为股票里都是和你一样用屁股决定脑袋的人在炒股多。