最近在看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());
}
}
}
注:
另外一个 使用了泛型之后的版本,链接如下:
使用泛型之后的版本,点这里!
永远不要弄丢最初的自己
----不忘初心,方得始终。