阅读之前看这里👉:博主是一名与大家共同学习的学生,博客记录的是在学习过程中一些总结,也希望和大家一起进步,在记录之时,未免存在很多疏漏和不全,如有问题,还请私聊博主指正。
博客地址:天阑之蓝的博客,学习过程中不免有困难和迷茫,希望大家都能在这学习的过程中肯定自己,超越自己,最终创造自己。
1.Comparable定义
Interface Comparable<T>
参数类型 : T—该对象可以与之进行比较的对象的类型 。
- 此接口对实现该接口的每个类的对象强加了总体排序。 该排序称为类的自然排序 ,而该类的compareTo方法被称为其自然比较方法 。
- 可以通过Collections.sort (和Arrays.sort )自动对实现此接口的对象的列表(和数组)进行排序。实现该接口的对象,可以使用如在键sorted map或作为在元件sorted set ,而不需要指定一个comparator 。
- 当且仅当 e1.compareTo(e2) == 0 ,对于类 C 的每个 e1 和 e2 具有与 e1.equals(e2) 相同的布尔值时,才说类 C 的自然顺序与 equals 一致。请注意, null 不是任何类的实例,即 e.equals(null) 返回 false,e.compareTo(null) 也应该抛出 NullPointerException。
- 强烈建议(虽然不是必需的)自然顺序与 equals 一致。之所以如此,是因为没有显式比较器的排序集(和排序映射)在与自然顺序与 equals 不一致的元素(或键)一起使用时表现得“奇怪”。特别是,这样的排序集合(或排序映射)违反了集合(或映射)的一般契约,它是根据 equals 方法定义的。
-
例如,如果将两个键 a 和 b 相加使得 (!a.equals(b) && a.compareTo(b) == 0)到一个不使用显式比较器的有序集合,则第二个加法操作返回 false (并且排序集的大小不会增加)因为从排序集的角度来看 a 和 b
是等效的。 - 几乎所有实现 Comparable 的 Java 核心类都具有与 equals 一致的自然顺序。一个例外是java.math.BigDecimal,它的自然排序将 BigDecimal 对象等同于具有相同的值和不同的精度(例如 4.0 和4.00)。
- 数学上定义给定类 C 的自然排序的关系是:
{(x, y) such that x.compareTo(y) <= 0} - 此总顺序的商为:
{(x, y) such that x.compareTo(y) == 0}. - 从compareTo 的定义可以立即得出该商数是一个等价关系 C ,并且自然排序是C 上的全序。当我们说一个类的自然排序与equals一致时,意思是自然排序是由类的 equals(Object) 方法定义的等价关系:
{(x, y) such that x.equals(y)}.。
2.Comparable的实例学习
说明:TreeSet调用集合元素的compareTo方法来比较元素的大小关系,然后将集合元素按照升序排列(从小到大,BigDecimal, BigInteger, Byte, Double, Float, Integer, Long, Short 是按数字大小排序。Character 按字符的Unicode值的数字大小排序。String 按字符串中字符的Unicode值排序)。
要求TreeSet集合中的元素实现Comparable接口。在compareTo方法中编写比较规则,在该方法中,比较当前对象(ths)和参数对象o(严格上说比较的是对象中的数据,比如按照对象的年龄排序)。
2.1代码
public class TreeSetDemo {
public static void main(String[] args) {
//创建集合对象
TreeSet<Student> treeSet = new TreeSet<Student>();
//创建学生对象
Student s1 = new Student("xishi",29);
Student s2 = new Student("wangzhaojun",30);
Student s3 = new Student("diaocan",28);
Student s4 = new Student("yangyuhuan",31);
//添加元素
treeSet.add(s1);
treeSet.add(s2);
treeSet.add(s3);
treeSet.add(s4);
//遍历
for (Student s : treeSet){
System.out.println(s);
}
}
}
接下来测试,在学生类中实现了Comparable接口,并重写compareTo(T o)方法后,操作类的运行情况
在Student类中重写compareTo(T o)方法代码:(通过返回值的不同,来影响排序结果,具体看运行结果)
@Override
public int compareTo(Student o) {
return 0;
}
/*
运行结果:xishi,29
*/
@Override
public int compareTo(Student o) {
return 1;
}
/*
运行结果:
xishi,29
wangzhaojun,30
diaocan,28
yangyuhuan,31
*/
@Override
public int compareTo(Student o) {
return -1;
}
/*
运行结果:
yangyuhuan,31
diaocan,28
wangzhaojun,30
xishi,29
*/
结论:
通过三次修改返回值,从运行结果中可以得出结论:
当返回值为0时,认为是重复元素,不进行存储。
当返回值为1时,按照存储顺序,正向排序(升序)(因为是正向排序,可以理解从小到大的顺序)
当返回值为-1时,按照存储顺序,逆向排序(降序)(同理)
于是,可以通过控制返回值的不同来控制不同的排序结果。接下来实现上面的需求。
对compareTo方法在进行修改,先使得年龄以升序的方式排序,代码:
@Override
public int compareTo(Student s) {
int num = this.age - s.age;
return num;
}
/*
运行结果:
diaocan,28
xishi,29
wangzhaojun,30
yangyuhuan,31
*/
接下来完善要求,年龄相同时,按照姓名的字母顺序排序,代码如下:
//学生类中重写代码部分及运行结果
@Override
public int compareTo(Student s) {
int num = this.age - s.age;
//如果年龄相同则比较姓名字母顺序(升序)排列。
int num2 = num == 0 ? this.name.compareTo(s.name) : num;
return num2;
}
/*
运行结果:
diaocan,28
xishi,29
wangzhaojun,30
linqingxia,31
yangyuhuan,31
*/
———————————————————————————————————————————————
博主码字不易,大家关注点个赞转发再走呗 ,您的三连是激发我创作的源动力^ - ^

本文详细介绍了Java中的Comparable接口及其自然排序的概念,包括Comparable接口的定义、自然排序与equals的一致性,以及Comparable接口在实例(如TreeSet)中的应用。通过示例代码展示了如何在自定义类中实现Comparable接口,以控制对象的排序方式,如年龄升序、姓名字母顺序等。

975

被折叠的 条评论
为什么被折叠?



