TreeSet/map的去重和排序
TreeSet/map的去重和排序
TreeSet集合
TreeSet集合是可以给元素进行重新排序的一个Set接口的实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator进行排序,具体取决于使用的构造方法。
存储特点:
无序存储,排重,通过红黑树实现的集合,可以给元素进行重新排序
我们知道Set集合中的元素都是无序不重复的,而TreeSet中的元素却是有序(这里的有序是按照字典顺序排列,基本数据类型和String的话字母按照a-z,数字按照大小)不重复的,所以在保存没有实现排序功能的**对象(注意是对象类型)**时,他不知道应该怎么进行进行排序,直接往TreeSet集合中添加没有实现Compareable或者没有传入构造器时就会报错:
Exception in thread “main” java.lang.ClassCastException: Student cannot be castto java.lang.Comparable
at java.util.TreeMap.compare(TreeMap.java:1188)
at java.util.TreeMap.put(TreeMap.java:531)
at java.util.TreeSet.add(TreeSet.java:255)
at TreeSetOrderDemo.main(TreeSetOrderDemo.java:18)
我们在使用TreeSet集合时候必须要实现Compareable接口来实现排序,实现排序有两种方式。
第一种排序方式:对象类中实现Compareable接口并重写其方法:
package set;
public class Student implements Comparable<Student>{
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Student o) {
int n1=this.name.compareTo(o.name);
int n2=this.age-o.age;
return n1==0?n2:n1;
}
/* @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);
}
*/
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 +
'}';
}
}
这里Student类中实现了Compable接口并重写了其方法,按照自定义的规则来排序,同时还具有去重的功能:
` public int compareTo(Student o) {
int n1=this.name.compareTo(o.name);
int n2=this.age-o.age;
return n1==0?n2:n1;
}
这里按先按姓名的默认来排序,姓名相同的话按照年龄的升序排序,两者都为0的话就是重复元素,则不添加。年龄降序的话反过来就行,其中返回值等于0证明元素属性相同,大于0放到二叉树右边,小于0 放二叉树左边然后根据二叉树的排序进行取出达到排序去重目的。
第二种实现方式
元素需要通过java.util.Comparator接口(比较器)中的compare方法进行比较大小,并排序。
compare方法除了可以进行排序外,还有排重的功能,但是必须在compare方法中对类中所有的属性值都进行判断,否则不比较那个属性,排重就会忽略哪个属性
TreeSet集合中的无参数构造方法默认使用自然排序的方式对元素进行排序,使用TreeSet集合的定制排序时,创建集合对象不可以直接使用无参数构造方法,需要使用传入一个Comparator比较器的构造方法创建集合对象。
也可以定义一个Comparator接口的,新建一个实现类,作为参数传递到集合的构造中
代码块如下( MyComparator()是Comparator和接口实现类):
Comparator实现类作为参数传入
package set;
import java.util.Comparator;
public class MyComparator implements Comparator<Student> {
@Override
public int compare(Student o1, Student o2) {
int n1= o1.getName().compareTo(o2.getName());
int n2=o1.getAge()-o2.getAge();
return n2==0?n1:n2;
}
}
package set;
import java.util.TreeSet;
public class TreeSetDemo2 {
public static void main(String[] args) {
/*两种方式实现treeset插入排序
1.在元素类中实现Comparable<Student>接口
2.自定义比较器 实现Comparator<Student>接口 在创建集合的时候 声明一下
* */
TreeSet<Student> treeSet1=new TreeSet<>(new MyComparator());//无序的 但是可以根据字典顺序进行排序
treeSet1.add(new Student("jack",23));
treeSet1.add(new Student("rose",24));
treeSet1.add(new Student("mike",25));
treeSet1.add(new Student("lily",26));
treeSet1.add(new Student("jack",24));
System.out.println("元素个数:"+treeSet1.size());
System.out.println(treeSet1);
}
}
直接传入匿名对象 Comparator重写排序方法
TreeSet<Student> treeSet2=new TreeSet<>(new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
int n1= o1.getName().compareTo(o2.getName());
int n2=o1.getAge()-o2.getAge();
return n2==0?n1:n2;
}
});//无序的 但是可以根据字典顺序进行排序
treeSet1.add(new Student("jack",23));
treeSet1.add(new Student("rose",24));
treeSet1.add(new Student("mike",25));
treeSet1.add(new Student("lily",26));
treeSet1.add(new Student("jack",24));
System.out.println("元素个数:"+treeSet1.size());
System.out.println(treeSet1);
}
这样就是Comparator的两种是排序实现,TreeSet和HashSet的排序去重实现是一致的,只不过HashSet排序的是键,而treeSet排序的是元素本身。
下一篇: TreeSet集合