TreeSet容器实现元素自排序

谈到TreeSet,首先要对比一下HashSet,二者都是Set集合的子类。Set集合有存储的数值不能重复的特点,其中,HashSet,取的数据不是按照怎样存就是怎样取,他的底层是一个HashMap做的数据存储,是一个Hash表,他实现去重的方式是:该HashSet容器中存储的无论是Java提供的系统类,比如,String,还是自定义类Person,Student,重写hashCode和equals方法后,可以实现去重功能。看String源码,可以知道String重写父类Object的hashCode和equals方法,所以当HashSet存储字符串时,可以实现去重功能

而TreeSet,其底层算法采用红黑树,也是二叉树的一种,树的左节点值小于同一个父节点的右节点值,他的特点是可以对插入的值进行有序输出。有两种实现方式,一个是自定义类实现比较器Comparable接口或Comparator接口,比如自定义Person类实现Comparable或Comparator接口。如果实现Comparable接口,就要重写Comparable接口的comparaTo方法,如果重写Comparator接口,就要重写compara方法。另一种方式是自定义一个比较器,该自定义比较器实现Comparator或Comparable接口。第一种方式,当一个类中同时实现Comparable和Comparator接口,那么以Comparator接口定义的比较规则优先


下面代码演示两种方式的实现:

第一种:自定义类实现比较器接口。

package com.jin.entity;

import java.util.Comparator;

import lombok.AllArgsConstructor;
import lombok.Data;

@Data
@AllArgsConstructor
public class Person implements Comparable<Object>, Comparator<Object>{

private String name;

private String pwd;

private Integer age;
/*
compareTo是Comparable接口方法
*/
@Override
public int compareTo(Object o) {
if(o instanceof Person) {
Person p = (Person) o;
/*
* 比较规则:先比较年龄,再比较姓名,最后比较密码
*/
if(this.age.equals(p.getAge())) {
if(this.name.equals(p.getName())) {
if(this.pwd.equals(p.getPwd())) {
return 0;
} else {
return this.pwd.compareTo(p.getPwd());
}
} else {
return this.name.compareTo(p.getName());
}
} else {
return this.age - p.getAge();
}
}
return -1;
}

/*
compare方法是Comparator接口方法
*/
@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person) {
Person s1 = (Person) o1;
Person s2 = (Person) o2;
/*
* 定义比较规则:先比较姓名,再比较年龄,最后比较密码
*/
if(s1.getName().equals(s2.getName())) {
if(s1.getAge().equals(s2.getAge())) {
if(s1.getPwd().equals(s2.getPwd())) {
return 0;
} else {
return s1.getPwd().compareTo(s2.getPwd());
}
} else {
return s1.getName().compareTo(s2.getName());
}
} else {
return s1.getAge() - s2.getAge();
}
}
return 0;
}
}

下面是TreeSet的应用:

TreeSet<Person> set = new TreeSet<Person>();

Person p1 = new Person("dbc", "admin", 22);
Person p2 = new Person("abc", "admin", 23);
Person p3 = new Person("abb", "admi", 23);
Person p4 = new Person("abc", "admin", 24);

set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);

System.out.println(set.size());
set.forEach(p -> { //p代表一个Person对象,用到了Java8的Lamda表达式
System.out.println(p); //由于同时用到了Comparable和Comparator接口,所以会优先按照Comparator接口定义的规则走
});


第二种方式:自定义一个比较器实现Comparator或Comparable接口
案例如下:

package com.jin.set;

import java.util.Comparator;

import com.jin.entity.Person;

public class MyComparator implements Comparator<Object> {

@Override
public int compare(Object o1, Object o2) {
if(o1 instanceof Person && o2 instanceof Person) {
Person s1 = (Person) o1;
Person s2 = (Person) o2;
/*
* 定义比较规则,年龄第一,名字第二,密码第三
*/
if(s1.getAge().equals(s2.getAge())) {
if(s1.getName().equals(s2.getName())) {
if(s1.getPwd().equals(s2.getPwd())) {
return 0;
} else {
return s1.getPwd().compareTo(s2.getPwd());
}
} else {
return s1.getName().compareTo(s2.getName());
}
} else {
return s1.getAge() - s2.getAge();
}
}
return -1;
}
}

下面是TreeSet的应用:

TreeSet<Person> set = new TreeSet<Person>(new MyComparator());

Person p1 = new Person("dbc", "admin", 22);
Person p2 = new Person("abc", "admin", 23);
Person p3 = new Person("abb", "admi", 23);
Person p4 = new Person("abc", "admin", 24);

set.add(p1);
set.add(p2);
set.add(p3);
set.add(p4);

System.out.println(set.size());
set.forEach(p -> {
System.out.println(p);
});

 

posted @ 2019-05-28 11:48  靳帅  阅读(190)  评论(0编辑  收藏  举报