利用TreeSet实现Comparable、Comparator的两种排序方式(自然排序、定制排序)

最近在看Javase中集合的相关内容,其中TreeSet作为Set接口的实现类之一,采用的存储结构是:红黑树。
要求为:
1)向TreeSet中添加的属性,要求是相同类的对象;
2)在每次通过add()向树中插入元素时,需要先通过 比较(comparato()或者compare()),确保树种不插入相同的元素;这里与Set接口的其他实现类不同,因为Set存储的数据:无序、不可重复,所以在调用add()进行插入操作时,是一定要进行大小的比较的,只不过Set接口的其他两个实现类HashSet、LinkedHashSet使用的都是:要插入的对象对应的类中的重写后的equals()
3)注意:在对插入元素进行比较大小这个方面,这里(TreeSet)与Set接口的其他实现类不同,因为Set存储的数据:无序、不可重复,所以在调用add()进行插入操作时,是一定要进行大小的比较的,只不过Set接口的其他两个实现类HashSet、LinkedHashSet使用的都是:要插入的对象对应的类中的重写后的equals()

题目:

创建5个employee的对象,并把这些对象放入treeset集合中
* 分别按照以下两种方式对接中的元素进行排序:
1)使employee实现comparable接口,并按照排序
(先创建treeset,并且使用add()加入元素,另外再写一个comparato()即可,因为treeset中,本质上是使用comparato()去比较的)
2)创建treeset时传入com对象(用带有形参的构造器),按生日日期的先后顺序,进行排序

代码实现:

1)Employee类:

public class Employee implements Comparable{

	private String name;
	private int age;
	private MyDate birthday;
	//构造器
	public Employee(String name, int age, MyDate birthday) {
		super();
		this.name = name;
		this.age = age;
		this.birthday = birthday;
	}
	public Employee() {
		super();
	}
	//get、set方法
	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;
	}
	public MyDate getBirthday() {
		return birthday;
	}
	public void setBirthday(MyDate birthday) {
		this.birthday = birthday;
	}
	@Override
	public String toString() {
		return "Employee [name=" + name + ", age=" + age + ", birthday=" + birthday + "]";
		//这里的birthday调用的是mydate,自己的toString
	}
	
	//按照姓名的顺序排
	@Override
	public int compareTo(Object o) {
		
		if(o instanceof Employee) {
			//先强转
			Employee e = (Employee) o;
			//比较大小并返回
			//按照 姓名 从小到大排
			return this.name.compareTo(e.name);
		}
		//用return 0 ,也可以:
		//因为treeset中不能放相同数据,return 0,表示是相同数据------>放不进树里来
		return 0;
	}
}

2)MyDate类:

public class MyDate implements Comparable {

	private int year;
	private int month;
	private int day;

	// 构造器
	public MyDate() {
		super();
	}

	public MyDate(int year, int month, int day) {
		super();
		this.year = year;
		this.month = month;
		this.day = day;
	}

	// get、set方法
	public int getYear() {
		return year;
	}

	public void setYear(int year) {
		this.year = year;
	}

	public int getMonth() {
		return month;
	}

	public void setMonth(int month) {
		this.month = month;
	}

	public int getDay() {
		return day;
	}

	public void setDay(int day) {
		this.day = day;
	}

	@Override
	public String toString() {
		return "MyDate [year=" + year + ", month=" + month + ", day=" + day + "]";
	}

	//披着自然排序的外衣,实际上是employeetest类中实现定制排序的一部分
	@Override
	public int compareTo(Object o) {

		if (o instanceof MyDate) {
			MyDate m = (MyDate) o;

			// 先比较 年
			int minusYear = this.getYear() - m.getYear();
			if (minusYear != 0) {
				// 年份不一样
				return minusYear;
			}
			// 年份一样
			int minusMonth = this.getMonth() - m.getMonth();
			if (minusMonth != 0) {
				// 月份不一样
				return minusMonth;
			}
			// 月份也一样

			// 比较日期的逻辑,也可以写成:
			return this.getDay() - m.getDay();
		}

		return 0;
	}

}

3)EmployeeTest类:

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

import org.junit.Test;

public class EmployeeTest {
	// 问题一:使用 自然排序
	@Test
	public void test1() {
		TreeSet set = new TreeSet();

		Employee e1 = new Employee("liudehua", 55, new MyDate(1965, 5, 4));
		Employee e2 = new Employee("zhangxueyou", 43, new MyDate(1987, 5, 4));
		Employee e3 = new Employee("guofucheng", 44, new MyDate(1987, 5, 4));
		Employee e4 = new Employee("liming", 51, new MyDate(1954, 8, 1));
		Employee e5 = new Employee("liangchaowei", 21, new MyDate(1978, 12, 4));
		/*
		 * 如果用的是:中文的名字 用的是:按照UTF-8的顺序排的,可能会产生:类似于--黎明 在 张学友的后边。
		 * ----但是,在手机通讯录中,就不会出现这样的情况: 因为不是按照汉字对应的UTF-8中的值进行比较; 而是先去找汉字对应的拼音,再根据拼音去比较
		 */

		set.add(e1);
		set.add(e2);
		set.add(e3);
		set.add(e4);
		set.add(e5);
		/*
		 * treeset要求放数据,要用红黑树去放, ------>实际上是:先比较完大小,再放入数据的
		 */
		// 输出
		Iterator iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}

	}

	// 问题二:按照生日排序:
	@SuppressWarnings("unchecked")
	@Test
	public void test2() {

		//此时treeset的构造器,应该选择有参数的构造器----采用的是:匿名实现类的匿名对象,因为就在这里用一次(这样写的话方便)
		
		TreeSet set = new TreeSet(new Comparator() {

			@Override
			public int compare(Object o1, Object o2) {
				if(o1 instanceof Employee && o2 instanceof Employee) {
					Employee e1 = (Employee) o1;
					Employee e2 = (Employee) o2;
					
					//注意:日期的date类也可以默认进行自然排序,认为数小的就是小
					MyDate b1 = e1.getBirthday();
					MyDate b2 = e2.getBirthday();
//					
					//方式一:将比较mydate的逻辑写在 comparable的匿名实现类 的匿名对象中去
//					//先比较 年
//					int minusYear = b1.getYear() - b2.getYear();
//					if(minusYear != 0) {
//						//年份不一样
//						return minusYear;
//					}
//					//年份一样
//					int minusMonth = b1.getMonth()- b2.getMonth();
//					if(minusMonth != 0) {
//						//月份不一样
//						return minusMonth;
//					}
//					//月份也一样
//					
					int minusDay = b1.getDay() - b2.getDay();
					if(minusDay != 0) {
						//如果日期不一样
						return minusDay;
					}else {
						//年月日 都一样
						return 0;
					}
//					//比较日期的逻辑,也可以写成:
//					return b1.getDay() - b2.getDay();
					
					
					//方式二:将mydate的比较写在 mydate类中去
					/*
					 * 让mydate去implements comparable,
					 * 在mydate中重写comparato()
					 * 在这里(comparator的匿名实现类的匿名对象中 重写的 compare方法中),
					 * 调用mydate中的重写的comparato()即可
					 */
					//手动实现mydate类中compareto()的重写,以便在这里可以直接调用
					return b1.compareTo(b2);
					
					
				}
				
				return 0;

			}
			
		});

		Employee e1 = new Employee("liudehua", 55, new MyDate(1965, 5, 4));
		Employee e2 = new Employee("zhangxueyou", 43, new MyDate(1987, 5, 4));
		Employee e3 = new Employee("guofucheng", 44, new MyDate(1987, 5, 4));
		Employee e4 = new Employee("liming", 51, new MyDate(1954, 8, 1));
		Employee e5 = new Employee("liangchaowei", 21, new MyDate(1978, 12, 4));
		/*
		 * 如果用的是:中文的名字 用的是:按照UTF-8的顺序排的,可能会产生:类似于--黎明 在 张学友的后边。
		 * ----但是,在手机通讯录中,就不会出现这样的情况: 因为不是按照汉字对应的UTF-8中的值进行比较; 而是先去找汉字对应的拼音,再根据拼音去比较
		 */

		set.add(e1);
		set.add(e2);
		set.add(e3);
		set.add(e4);
		set.add(e5);
		/*
		 * treeset要求放数据,要用红黑树去放, ------>实际上是:先比较完大小,再放入数据的
		 */
		// 输出
		Iterator iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next());
		}

	}

}


注:
另外一个 使用了泛型之后的版本,链接如下:
使用泛型之后的版本,点这里!



永远不要弄丢最初的自己
----不忘初心,方得始终。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值