TreeSet
TreeSet 储存自定义对象
cannot be cast tojava.lang.Comparable,遇到这个异常错误,就是说treeMap(或者treeSet)并不知道该如何put(add),就会报这个异常错误。
- 自定义的对象需要实现Comparable接口。(String除外)
自然排序与定制排序的比较
-
两种方法各有优劣, 用Comparable 简单, 只要实现Comparable 接口的对象直接就成为一个可以比较的对象
但是需要修改源代码。 -
用Comparator 的好处是不需要修改源代码, 而是另外实现一个比较器, 当某个自定义
的对象需要作比较的时候,把比较器和对象一起传递过去就可以比大小了, 并且在Comparator 里面用户可以自
己实现复杂的可以通用的逻辑,使其可以匹配一些比较简单的对象,那样就可以节省很多重复劳动了。 -
compareTo就是比较两个值,如果前者大于后者,返回1,等于返回0,小于返回-1,
-
我下面给出了例子,由于比较的变量我用的是int,int型可以直接比较,所有没有用到compareTo比较,
-
如果声明的是Date、String、Integer或者其他的,可以直接使用compareTo比较,
java内外部比较器(Comparator、Comparable)
import java.util.*;
public class TreeSetDemo {
public static void main(String[] args) {
TreeSet<Student> ts = new TreeSet<Student>();
ts.add(new Student("AA", 22));
ts.add(new Student("BB", 20));
ts.add(new Student("CC", 18));
ts.add(new Student("DD", 19));
// Iterator<Student> it = ts.iterator();
// while (it.hasNext()) {
// System.out.println(it.next());
// }
}
}
class Student implements Comparable// 该接口强制让学生具备比较性
{
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Object obj)// 这个方法在调用add方法时候强制默认自动调用
{
if (obj instanceof Student) {// 比较的前提:两个对象的类型相同
Student s = (Student) obj;
/*
* 当采用compareTo(Object obj)方法比较对象时,都需要将被比较对象obj强制类型转换成相同类型,
* 因为只有相同类的两个实例才能比较大小
*/
System.out.println(this.name + "比较" + s.name);
return this.name.compareTo(s.name);
}
// if(this.age>s.age)
// return 1;
// if(this.age==s.age)
// {
// return this.name.compareTo(s.name);//String类已经实现CompareTo
// }if(this.age<s.age)
// return -1;
// }
// return 0;
return 0;
}
public String getName() {
return name;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Student other = (Student) obj;
if (age != other.age)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
return true;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student [name=" + name + ", age=" + age + "]";
}
}
自然排序
注意:
Java 9 改进了 TreeSet 实现,如果采用自然排序的 Set 集合的元素没有实现 Comparable 接口,程序就会立即引发
ClassCastException
具体实现
package www.xq.collection;
import jdk.nashorn.internal.runtime.regexp.joni.constants.AsmConstants;
import org.junit.Test;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @author xqstart
* @date 2018/10/11 - 15:47
*/
public class TestTreeSet2 {
public static void main(String[] args) {
TreeSet<Student1> students = new TreeSet<Student1>();
students.add(new Student1("aa", 23));// 往集合添加元素
students.add(new Student1("BB", 24));
students.add(new Student1("cc", 34));
students.add(new Student1("dd", 23));
students.add(new Student1("ff", 21));
Iterator<Student1> iterator = students.iterator();//初始化迭代器,遍历集合中的所有元素
while (iterator.hasNext()) {
Student1 student1 = iterator.next();
System.out.println(student1.getName() + "---->" + student1.getAge());
}
}
}
class Student1 implements Comparable<Object> {
private String name;
private int age;
// 复写构造函数初始化姓名跟年龄
Student1(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
@Override
public int compareTo(Object o) {
if(!(o instanceof Student1)) // 第三:判断对象是否是特定类的一个实例
throw new RuntimeException("不是学生对象");
Student1 s = (Student1)o;
// 第四:当前对象的年龄与插入对象的年龄进行比较,当前年龄大于插入对象的年龄时,返回1,
// 此时将插入二叉树的右边,当等于时,返回0,进行次要条件的比较,再次调用;当小于时,返回-1;
if (this.age > s.age) // 判断当前对象年龄是否大于传入的对象年龄
return 1;
if (this.age == s.age) // 如果当前年龄等于传入对象的年龄,则比较姓名是否相同
{
return this.name.compareTo(s.name);
}
return -1;
}
}
定制排序
具体实现:
package www.xq.collection;
import java.util.Iterator;
import java.util.TreeSet;
/**
* @author xqstart
* @date 2018/10/11 - 16:39
*/
public class TestTreeSet {
public static void main(String[] args) {
TreeSet<Student> students = new TreeSet<>(new MyComparator());//创建一个 TreeSet 的集合
/**
* 要实现定制排序,需要在创建TreeSet集合对象时,提供一个一个Comparator对象,
* 该对象里负责集合元素的排序逻辑;
*/
students.add(new Student("aa", 23));// 往集合添加元素
students.add(new Student("BB", 24));
students.add(new Student("cc", 34));
students.add(new Student("dd", 23));
students.add(new Student("ff", 21));
Iterator<Student> iterator = students.iterator();//初始化迭代器,遍历集合中的所有元素
while (iterator.hasNext()) {
Student student = iterator.next();
System.out.println(student.getName() + "---->" + student.getAge());
}
}
}
Student类设计
package www.xq.collection;
import java.util.Comparator;
/**
* @author xqstart
* @date 2018/10/11 - 15:51
*/
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 int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
class MyComparator implements Comparator{ //第一步:实现Comparator接口
@Override
public int compare(Object o1, Object o2) { //第二步:实现一个campare方法
//判断对象是否是特定类的一个实例
if(o1 instanceof Student & o2 instanceof Student){
Student s1 = (Student)o1;
Student s2 = (Student)o2;
if(s1.getAge() > s2.getAge()){
return 1;
}else if(s1.getAge() < s2.getAge()){
return -1;
}
}
return 0;
}
}