今天看了看 泛型的使用(基于集合),对于之前的题目,进行一下技术更新,实现:在使用泛型的基础上的、利用TreeSet结构、实现Comparable、Comparator的两种排序方式(自然排序、定制排序)的 存储对象到集合中的操作。
具体如下:
题目:
创建5个employee的对象,并把这些对象放入treeset集合中
* 分别按照以下两种方式对接中的元素进行排序:
1)使employee实现comparable接口,并按照排序
(先创建treeset,并且使用add()加入元素,另外再写一个comparato()即可,因为treeset中,本质上是使用comparato()去比较的)
2)创建treeset时传入com对象(用带有形参的构造器),按生日日期的先后顺序,进行排序
代码实现:
1)Employee类:
public class Employee implements Comparable<Employee>{
//Comparable的实现类想用来比较谁,表示泛型的<>内就写谁------Employee
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
}
//加入 泛型 以后,自动生成的需要 重写的方法compareto()
@Override
public int compareTo(Employee o) {
// 因为此时,传过来的参数 一定是Employee类型的对象(由于采用了泛型)
return this.name.compareTo(o.name);
}
//没有指明泛型时的写法
//按照姓名的顺序排
// @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类:
//想使用哪个类的排序的能力,implements Comparable<>的<>中,就写上哪个类
//这里使用的是:MyDate
public class MyDate implements Comparable<MyDate> {
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 + "]";
}
//使用泛型之后:实现定制排序(仍旧是按照日期的先后----年份的数字小的在前边,年份的数字大的在后边)
@Override
public int compareTo(MyDate o) {
//因为泛型的存在 o 是MyDate类的对象,所以可以直接比较
//先比较年份
if((this.getYear() - o.getYear()) != 0) {
//此时说明,不是同一年出生,可以直接加入
return this.getYear() - o.getYear();
}
//是同一年的话,开始比较月份
if((this.getMonth() - o.getMonth()) != 0) {
//月份不一样的话,不用继续判断,可以直接加入
return this.getMonth() - o.getMonth();
}
//比较日期的写法1:
// //年、月都相同,开始比较具体的出生日期(day的值)
// if((this.getDay() - o.getDay()) != 0) {
// //出生的具体的day是不一样的,也是可以直接加入treeset中的
// return this.getDay() - o.getDay();
// }
// //年月日都相同,不可以加入------直接return 0 即可,因为treeset中return 0表示不加入;return 非0的话,对应着加在左边还是右边
// return 0;
//比较日期的写法2:
return this.getDay() - o.getDay(); //因为没有else的情况了,所以可以直接这样return
}
//使用泛型之前
//披着自然排序的外衣,实际上是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 {
/*
* 关于employee的测试: 创建5个employee的对象,并把这些对象放入treeset集合中(下一章中,treeset需要使用泛型来定义)
* 分别按照以下两种方式对接中的元素进行排序:
* 1)使employee实现comparable接口,并按照排序
* (先创建treeset,并且使用add()加入元素,另外再写一个comparato()即可,因为treeset中,本质上是使用comparato()去比较的)
* 2)创建treeset时传入com对象(用带有形参的构造器),按生日日期的先后顺序,进行排序
*
*/
// 问题一:使用 自然排序
@Test
public void test1() {
TreeSet<Employee> set = new TreeSet<Employee>();
//JDK7时的小特性:类型推断
/*
* 上面的创造TreeSet对象的句子,可以省略为:
* TreeSet<Employee> 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<Employee> iterator = set.iterator();
while (iterator.hasNext()) {
Employee employee = iterator.next();
System.out.println(employee);
}
}
// 问题二:按照生日排序:定制排序
@SuppressWarnings("unchecked")
@Test
public void test2() {
//此时treeset的构造器,应该选择有参数的构造器----采用的是:匿名实现类的匿名对象,因为就在这里用一次(这样写的话方便)
//这里采用了类型推断
//定制排序:比较得是谁new Comparator<>,它的<>中就填的是 哪个类型
TreeSet<Employee> set = new TreeSet<>(new Comparator<Employee>() {
//使用泛型之后的写法
@Override
public int compare(Employee o1, Employee o2) {
return o1.getBirthday().compareTo(o2.getBirthday());
}
//使用泛型之前的写法
// @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的匿名实现类 的匿名对象中去
//
// //方式二:将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<Employee> iterator = set.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
}
}
努力不一定成功,不努力一定很轻松。
加油!