自然排序接口Comparable和比较器Comparator

java基础 专栏收录该内容
3 篇文章 0 订阅

对类实现整体排序须使用Comparable接口

看如下错误:

Exception in thread “main” java.lang.ClassCastException: class_chapter.StudentExample cannot be cast to java.lang.Comparable

使用TreeSet存储对象是其自带一定规则的排序方法,但对复杂的对象排序须使用Comparable不然会吹西安上面的错误。

comparable是一个接口,其中compareTo()方法定义了排序规则,可以对复杂的对象进行排序。

代码部分:

//测试类
public class ComparableChapter {
	
	public static void main(String[] args) {
		
	
	TreeSet<StudentExample> ts=new TreeSet<StudentExample>();
	
	StudentExample s1=new StudentExample("s001","小明","男",20,95);
	
	StudentExample s2=new StudentExample("s002","小王","男",20,90);
	StudentExample s3=new StudentExample("s003","小花","女",21,93);
	
	ts.add(s1);
	ts.add(s2);
	ts.add(s3);
	
	for(StudentExample st1:ts) {
			System.out.println(st1);
		}
	}

//学生类
public class StudentExample{
	private String id;
	private String name;
	private String sex;
	private int age;
	private double grade;
	
	public String toString() {
		return id+"\t\t"+name+"\t\t"+sex+"\t\t"+age+"\t\t"+grade;
	}
	
	public void setId(String id) {
		this.id=id;
	}
	public String getId() {
		return this.id;
	}
	
	public void setNmae(String name) {
		this.name=name;
	}
	public String getNmae() {
		return this.name;
	}
	
	public void setSex(String sex) {
		this.sex=sex;
	}
	public String getSex() {
		return this.sex;
	}
	
	public void setAge(int age) {
		this.age=age;
	}
	public int getAge() {
		return this.age;
	}
	
	public void setGrade(double grade) {
		this.grade=grade;
	}
	public double getGrade() {
		return this.grade;
	}
	
	
	public StudentExample() {
		
	}
	public StudentExample(String id,String name,String sex,int age,double grade) {
		this.id=id;
		this.name=name;
		this.sex=sex;
		this.age=age;
		this.grade=grade;
	}

}

由于未使用Comparable接口,会出现错误:Exception in thread “main” java.lang.ClassCastException: class_chapter.StudentExample cannot be cast to java.lang.Comparable

// 使用Comparable接口的学生类
public class StudentExample implements Comparable{            //实现Comparable类
	private String id;
	private String name;
	private String sex;
	private int age;
	private double grade;
	
	public String toString() {
		return id+"\t\t"+name+"\t\t"+sex+"\t\t"+age+"\t\t"+grade;
	}
	
	public void setId(String id) {
		this.id=id;
	}
	public String getId() {
		return this.id;
	}
	
	public void setNmae(String name) {
		this.name=name;
	}
	public String getNmae() {
		return this.name;
	}
	
	public void setSex(String sex) {
		this.sex=sex;
	}
	public String getSex() {
		return this.sex;
	}
	
	public void setAge(int age) {
		this.age=age;
	}
	public int getAge() {
		return this.age;
	}
	
	public void setGrade(double grade) {
		this.grade=grade;
	}
	public double getGrade() {
		return this.grade;
	}
	
	
	public StudentExample() {
		
	}
	public StudentExample(String id,String name,String sex,int age,double grade) {
		this.id=id;
		this.name=name;
		this.sex=sex;
		this.age=age;
		this.grade=grade;
	}

	@Override          
	public int compareTo(java.lang.Object o) {                                  //重写compareTo方法
		// TODO Auto-generated method stub
		return 1;                                                     //1表示第二个对象比前一个打,0表示其相等,-1表示比前一个小
	}

}

由于实现了Compareble类就可以正常打印了,并按照输入的顺序输出,如果重写的compareTo()方法返回-1就会逆序输出,返回0只会输出一个,其认为后面和前面的相同。
在这里插入图片描述

对类的属性实现整体排序使用Comparator接口

上面的Comparable实现了TreeSet存储对象的整体排序,那如果想根据存储对象的属性的大小对对象进行排序呢?这里要使用Comparator接口。

Comparator是一个类,compare()方法定义复杂的排序机制,来实现排序。

代码部分:

//测试类
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import class_chapter.Student;;
public class ComparatorChapter {
	public static void main(String[] agrs) {
		
	Comparator<Student> comparator=new Comparator<Student>() {

		@Override
		public int compare(Student o1, Student o2) {
			// TODO Auto-generated method stub
				int figture1=Integer.parseInt(o1.getSid().substring(1));                  //定义的学号是S001类型要比较大小截取S后面的部分,再转化未int类型
				int figture2=Integer.parseInt(o2.getSid().substring(1));
				int sum=figture1-figture2;
				int s=sum==0? o1.compareTo(o2) : sum;                   //comparaTo()方法通过返回值来排序,三元表达式,判断学号的差值是否等于0,两种表达式。
				return s;                                               //Comparator的compare()方法和compareTo()方法一样都是通过返回值来改变排序机制,1,0,-1
			}                                                           //这里返回o1.compareTo(o2)式从小大排序,如果不等于0,是负数就比上一个小,排在前面,是正数就不上一个大在后面
		
	};
		
	Student s3=new Student("s003","小王");
	Student s2=new Student("s002","小张");
	Student s1=new Student("s001","小李");
	
	TreeSet ts1=new TreeSet(comparator);         //再创建TreeSet是需要引入Comparetor对象,对TreeSet的对象排序
	
	ts1.add(s3);
	ts1.add(s2);
	ts1.add(s1);
	
	Iterator Iterator = ts1.iterator();
	while(Iterator.hasNext()) {
		System.out.println(Iterator.next());
	}
	
	
	
	
	}
}

//学生类
public class Student{
	private String sid;
	private String sname;
	
	public String toString() {             //注意当是String类型是一定要重写tostring方法不然输出collection_and_map.Teacher@7852e922
		return sid+" "+sname;
	}	
	
	public void setSid(String sid) {
		this.sid=sid;
	}
	public String getSid() {
		return this.sid;
	}
	
	public void setSname(String sname) {
		this.sname=sname;
	}
	public String getSname() {
		return this.sname;
	}
	
	public void Student() {
		
	}
	public Student(String sid,String sname) {
		this.setSid(sid);
		this.setSname(sname);
	}

	public int compareTo(Student o2) {
		// TODO Auto-generated method stub
		return 1;                 //该方法为collection_and_map的ComparatorChapter类重写,并调用,详情见StudentExanple类
		                         //返回1,后面比前面打排在当前对象的后面,-1表示小,0表示相等。
	}
}

运行结果:
在这里插入图片描述

可以看到,添加到TreeSet中的顺序有s1,s2,s3;而输出顺序却相反,原因是创建TreeSet时引入了Comparator
改变了排序规则,使从小到大排序。

值得关注的是,Comparable,和Comparator的作用都是排序,但作用对象却不一样。他们都重写了compareTo()方法。所以要熟悉该方法。Comparator还重写了compare()方法,定义了排序规则,两个方法类似注意区分。引入comparator对象可以使用匿名内部类的方法,会更简洁。
代码:

TreeSet<Student> ts2=new TreeSet<Student>(new Comparator<Student>() {

		@Override
		public int compare(Student stu1, Student stu2) {
			// TODO Auto-generated method stub
			int figture1=Integer.parseInt(stu1.getSid().substring(1));              
			int figture2=Integer.parseInt(stu2.getSid().substring(1));
			int sum=figture1-figture2;
			int s=sum==0? stu1.compareTo(stu2) : sum;                  
			return s;                 
		}
		
	});              //完整语句要有;不然会出错

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

参与评论 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:数字20 设计师:CSDN官方博客 返回首页

打赏作者

_小许_

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值