TreeSet的自然排序(Comparable)与定制排序(Compartor)

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 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
		// 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;
    }
}

你可能感兴趣的:(集合,集合框架,排序)