TreeSet 是一个可以对元素进行排序的容器。底层实际是用 TreeMap 实现的,内部维持了一个简化版的 TreeMap,通过 key 来存储 Set 的元素。 TreeSet 内部需要对存储的元素进行排序,因此,我们需要给定排序规则。
排序规则实现方式:
- 通过元素自身实现比较规则。
- 通过比较器指定比较规则。
在元素自身实现比较规则时,需要实现 Comparable 接口中的 compareTo 方法,该方法中用来定义比较规则。TreeSet 通过调用该方法来完成对元素的排序处理。
package TreeSet;
import java.util.Set;
import java.util.TreeSet;
public class TreeSetTest {
public static void main(String[] args) {
Set set = new TreeSet<>();
set.add("A");
set.add("B");
set.add("D");
set.add("E");
set.add("C");
for (String str: set) {
System.out.println(str);
}
System.out.println("----------------------");
Set personSet = new TreeSet<>();
Person person = new Person("AAA",18);
Person person1 = new Person("AAA",21);
Person person2 = new Person("BBB",18);
Person person3 = new Person("BBB",13);
personSet.add(person);
personSet.add(person1);
personSet.add(person2);
personSet.add(person3);
for (Person p: personSet){
System.out.println(p);
}
}
}
运行结果:
所以我们虽然加进去
我们先构造一个实体类:它包括姓名和id两个基本属性:
因为我们要构造实体对象,所以我们需要构造方法;
因为我们需要获取对象的值,所以我们需要get/set方法;
因为我们要输出的是对象的值而非存储位置的hashcode,所以我们需要重写toString方法;
因为我们要比较的是对象的具体值而非它的hashcode值,所以我们也要对java中的equals方法进行重写;
***因为Java中提供的compareTo函数是基于基本数据类型和String类型的比较,所以在对象比较的过程中我们也需要重写compraeTo方法; ***
package TreeSet; import java.util.Objects; public class Person implements Comparable{ private String name; private int age; public Person(String name, int age) { this.name = name; this.age = age; } //重写comparable方法就不会只是单纯比较字符了 @Override public int compareTo(Person o) { if (this.age > o.getAge()){ return 1; } if (this.age == o.age){ return this.name.compareTo(o.getName()); } return -1; } //重写equals方法比较的就不止是hashcode值了,而是开始比较内容 @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); } @Override public int hashCode() { return Objects.hash(name, 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; } //重写toString,输出时候就不会只出现地址值了 @Override public String toString() { return "Person{" + "name='" + name + ''' + ", age=" + age + '}'; } }
那么接下来我们自己创建一个比较器:
我们创建一个Student的实体类,属性依旧只有name和id
对它进行get/set方法获取,进行构造方法使用。对toString进行重写。也对equals方法进行重写。
package TreeSet;
import java.util.Objects;
public class Student{
private String name;
private int age;
public Student(String name, int age) {
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;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + ''' +
", age=" + age +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return age == student.age &&
Objects.equals(name, student.name);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
}
接下来我们再写一个构造器类:
这里我们一定是util包里面的comparator接口;
我们实现这个接口,
package TreeSet; import java.util.Comparator; public class StuComparator implements Comparator{ @Override public int compare(Student o1, Student o2) { if(o1.getAge()>o2.getAge()){ return 1; } if (o1.getAge() == o2.getAge()){ return o1.getName().compareTo(o2.getName()); //调用String的compareTo方法对字符串进行排序并进行返回(正数:大。负数:小。相等:0) } return -1; } }
主方法:
package TreeSet;
import java.util.Set;
import java.util.TreeSet;
public class TestComparator {
public static void main(String[] args) {
Set studentSet = new TreeSet<>(new StuComparator());
//在这里我们是可以调用我们所实现排序的比较器的规则进行排序
Student student = new Student("cde",18);
Student student1 = new Student("efg",13);
Student student2 = new Student("abc",18);
studentSet.add(student);
studentSet.add(student1);
studentSet.add(student2);
for (Student stu:studentSet ) {
System.out.println(stu);
}
}
}



