java程序员从笨鸟到菜鸟之(二十八)集合TreeSet排序之compareTo和compare方法

TreeSet

无参构造方法

特点:该set集合根据其元素的自然顺序进行排序;插入该 set 的所有元素都必须实现 Comparable 接口。另外所有这些元素都必须是相互可比较的。

分析:通过源码我们可以知道内部创建Comparable比较器对象,调用了元素键对象类型的compareTo方法

实现Comparable接口的常用类:Integer、String等

实例1

package org.westos_04;

import java.util.TreeSet;

public class TreeSetDemo {
	
	public static void main(String[] args){
		/*
           throw new IOException();-----不是太懂?
		   public TreeSet():无参构造:根据其元素的自然顺序进行排序
		   publict TreeSet(Comparaptr<E> com)
		 * 
		 */
		TreeSet<Integer> ts = new TreeSet<Integer>();//
		ts.add(20);//装箱: Integer i = Integer.valueOf(20);
		ts.add(18) ;
		ts.add(23) ;
		ts.add(22) ;
		ts.add(17) ;
		ts.add(24) ;
		ts.add(19) ;
		ts.add(18) ;
		ts.add(24) ;
		//增强for遍历元素
		for(Integer i : ts){
			System.out.print(i+ " ");//17 18 19 20 22 23 24 :唯一并且排序:自然排序(升序排序)
		}
	}
}

问题来了,如果自定义的类呢?显然也得实现Comparable接口。

由于Comparable接口只有一个非静态的方法,方法描述如下:

int compareTo(T o)------返回值表示两个对象的大小关系

因此必须实现compareTo的方法!!!

实例2

Student类

package org.westos_04;

//对于TreeSet集合存储自定义对象必须实现一个接口:Compareable接口
public class Student implements Comparable<Student>{
	
	private String name ;
	private int age ;
	public Student() {
		super();
		// TODO Auto-generated constructor stub
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	
	//重写了compareTo()方法
	@Override
	public int compareTo(Student s) {

		//排序的代码了,需要定义排序的条件
		//主要条件:按照学生的年龄从小到大进行排序
		int num =s.age - this.age ;//年龄从大到小 
		//当num==0认为年龄一样,年龄一样,不代表姓名的的内容是否相同,需要自己给出次要条件
		int num2 = num==0 ? this.name.compareTo(s.name): num ;
		return num2 ;
	}

	
}
测试类

package org.westos_04;

import java.util.TreeSet;

/**
 * TreeSet集合存储自定义对象并遍历
 * 		实现了compareable接口,重写了comapreTo()方法,里面的逻辑是一个排序条件:
 * 		需求:
 * 			按照学生的年龄从小到大进行排序:主要条件
 * 			对于自定义对象什么情况下保证元素是唯一的
 * 			成员变量的值相同,认为是同一个元素
 * 			主要条件给定,需要分析次要条件
 * 				
 * 		一个类中的元素想要自然排序,那么必须实现Compareable接口,实现compareTo(类名 对象名){}方法
 * 		
 * 按照正常存储对象的操作以及遍历对象出现了问题:
 * 类转换异常
 * java.lang.ClassCastException: org.westos_04.Student cannot be cast to java.lang.Comparable
 * 
 * @author Apple
 */
public class TreeSetDemo2 {
	
	public static void main(String[] args) {
		
		//创建TreeSet集合对象
		TreeSet<Student> ts = new TreeSet<Student>() ;//
		
		//创建学生对象
		Student s1 = new Student("linqingxia", 28) ;
		Student s2 = new Student("fengqingy", 28) ;
		Student s3 = new Student("gaoyuanyuan", 27) ;
		Student s4 = new Student("liushishi", 26) ;
		Student s5 = new Student("wanglihong", 29) ;
		Student s6 = new Student("zhangguorong", 30) ;
		Student s7 = new Student("zhangguorong", 30) ;
		
		ts.add(s1);
		ts.add(s2);
		ts.add(s3);
		ts.add(s4);
		ts.add(s5);
		ts.add(s6);
		ts.add(s7);
		
		//遍历
		for(Student s : ts){
			System.out.println(s.getName()+"---"+s.getAge());
		}
	}	
}
问题:如果自定义的类不实现该接口,出现 类转换异常

补充:关于compareTo的业务逻辑实现需要根据需求自己码!!!

常见分析流程:主要条件和次要条件

有参的构造方法

public TreeSet(Comparator<? super E> comparator)

比较器:在外部创建比较器----需要我们创建一个实现该接口的比较器对象

Comparator接口中的方法:int compare(T o1, T o2) 和equals()方法

方式1内部类的形式(节省代码量)

实例3  Student类

package org.westos_06;

public class Student {
	
	private String name ;
	private int age ;
	public Student() {
		super();
	}
	public Student(String name, int age) {
		super();
		this.name = name;
		this.age = age;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	
	
	
	
}
测试类

package org.westos_06;

import java.util.Comparator;
import java.util.TreeSet;


/**
 * 需求:按照学生姓名长度从小到大进行排序
 * 
 * //元素唯一性:取决返回值是否为0
 * 要使用TreeSet集合的比较器排序:
 * 	依赖于构造方法:
 * 			public TreeSet(Comparator<E> comparator)
 * 
 * 			两种方式实现比较器排序:
 * 					Comparator接口作为形式参数进行传递,需要该接口的子实现类对象
 * @author Apple
 */
public class TreeSetDemo {
	
	public static void main(String[] args) {
		//创建TreeSet集合使用比较器进行给元素进行排序
		//public TreeSet(Comparator<E> comparator):有参构造
		//方式1:自定义一个类,类实现Comparator接口,作为子实现类
		//方式2:可以使用接口的匿名内部类来实现:开发中,由于减少代码书写量,不需要自定义接口的子实现类,直接这种格式!
		/**
		 * 格式
		 * new 接口名或者类名(){
		 * 		重写方法() ;
		 * } 
		 */
//		TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()) ;
		TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {

			@Override
			public int compare(Student s1, Student s2) {
//				return 0;//返回值主要说明对象比较结果
				
				int num = s1.getName().length() - s2.getName().length() ;
				//次要条件:姓名长度一样,还要比较姓名的内容是否一样
				int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;
				
				//姓名长度和内容都一样,还需比较两个人的年龄是否一样
				int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
				
				return num3 ;
			}
			
		}) ;
		
		
		//创建学生对象
		Student s1 = new Student("gaoyuanyan", 27) ;
		Student s2 = new Student("liushishi", 22);
		Student s3 = new Student("fengqingy", 23) ;
		Student s4 = new Student("wuqilong", 35) ;
		Student s5 = new Student("gaoyuanyuan",27) ;
		Student s6 = new Student("zhangguorong",29) ;
		Student s7 = new Student("gaoyuanyuan",26) ;
		
		
		//添加元素
		ts.add(s1) ;
		ts.add(s2) ;
		ts.add(s3) ;
		ts.add(s4) ;
		ts.add(s5) ;
		ts.add(s6) ;
		ts.add(s7) ;
		
		//增强for遍历
		for(Student s : ts){
			System.out.println(s.getName()+"----"+s.getAge());
		}
	}
}

方式2:定义一个实现该接口子类,实现对象的比较

实例4 Student同上

自定义类:实现Comparator接口

package org.westos_06;

import java.util.Comparator;

//MyComparatpr是Comparator接口的子实现类
public class MyComparator implements Comparator<Student> {

	@Override
	public int compare(Student s1, Student s2) {
//		return 0;
//		按照学生姓名长度从小到大进行排序
		//int num = this.name.lengt()-s.name.length();
		//this--:s1
		//s---:s2
		
		int num = s1.getName().length() - s2.getName().length() ;
		//次要条件:姓名长度一样,还要比较姓名的内容是否一样
		int num2 = num==0 ? s1.getName().compareTo(s2.getName()): num ;
		//compareTo可以用的原因---s1.getName()是String--该类实现了Comparable的接口的方法
		//姓名长度和内容都一样,还需比较两个人的年龄是否一样
		int num3 = num2 ==0 ? s1.getAge() - s2.getAge() : num2 ;
		
		return num3 ;
	}

}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值