TreeSet

2019-01-24  本文已影响11人  蚂蚁绊倒象

TreeSet如何比较自定义对象

Java中的TreeSet是Set的一个子类,TreeSet集合是用来对象元素进行排序的,同样他也可以保证元素的唯一。
那TreeSet为什么能保证元素唯一,它是怎样排序的呢?先看一段代码:

public static void demo() {
    TreeSet<Person> ts = new TreeSet<>();
    ts.add(new Person("张三", 23));
    ts.add(new Person("李四", 13));
    ts.add(new Person("周七", 13));
    ts.add(new Person("王五", 43));
    ts.add(new Person("赵六", 33));
    System.out.println(ts);
}

执行结果:

出错,会抛出一个异常:java.lang.ClassCastException
显然是出现了类型转换异常。原因在于我们需要告诉TreeSet如何来进行比较元素,如果不指定,就会抛出这个异常

如何解决:

比较自定义对象

如何指定比较的规则,需要在自定义类(Person)中实现Comparable接口,并重写接口中的compareTo方法

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    ...
    public int compareTo(Person o) {
        return 0;                //当compareTo方法返回0的时候集合中只有一个元素
        return 1;                //当compareTo方法返回正数的时候集合会怎么存就怎么取
        return -1;                //当compareTo方法返回负数的时候集合会倒序存储
    }
}

为什么返回0,只会存一个元素,返回-1会倒序存储,返回1会怎么存就怎么取呢?原因在于TreeSet底层其实是一个二叉树机构,且每插入一个新元素(第一个除外)都会调用compareTo()方法去和上一个插入的元素作比较,并按二叉树的结构进行排列。

  1. 如果将compareTo()返回值写死为0,元素值每次比较,都认为是相同的元素,这时就不再向TreeSet中插入除第一个外的新元素。所以TreeSet中就只存在插入的第一个元素。
  2. 如果将compareTo()返回值写死为1,元素值每次比较,都认为新插入的元素比上一个元素大,于是二叉树存储时,会存在根的右侧,读取时就是正序排列的。
  3. 如果将compareTo()返回值写死为-1,元素值每次比较,都认为新插入的元素比上一个元素小,于是二叉树存储时,会存在根的左侧,读取时就是倒序序排列的。

利用上述规则,我们就可以按照年龄来排序了:

public int compareTo(Person o) {
    int num = this.age - o.age;                //年龄是比较的主要条件
    return num == 0 ? this.name.compareTo(o.name) : num;//姓名是比较的次要条件
}

按照姓名排序(依据Unicode编码大小),代码如下:

public int compareTo(Person o) {
    int num = this.name.compareTo(o.name);        //姓名是主要条件
    return num == 0 ? this.age - o.age : num;    //年龄是次要条件
}

按照姓名长度排序,代码如下:

public int compareTo(Person o) {
    int length = this.name.length() - o.name.length();                //比较长度为主要条件
    int num = length == 0 ? this.name.compareTo(o.name) : length;    //比较内容为次要条件
    return num == 0 ? this.age - o.age : num;                        //比较年龄为次要条件
}
TreeSet如何利用比较器比较元素

需求:现在要制定TreeSet中按照String长度比较String。
TreeSet中:

public class MyComparator implements Comparator<String> {
    @Override
    public int compare(String o1, String o2) {
        return o1.length() - o2.length();
    }
}

public void test(){
    TreeSet<String> treeSet = new TreeSet<>(new MyComparator());
    treeSet.add("abcdef");
    treeSet.add("abcd");
    treeSet.add("abc");
    treeSet.add("abcde");
    for (String s : treeSet) {
        System.out.println("长度排序:" + s);
    }
}

打印结果:

I/System.out: 长度排序:abc
I/System.out: 长度排序:abcd
I/System.out: 长度排序:abcde
I/System.out: 长度排序:abcdef

List集合中:

public class Person{
    String name;
    int age;

    public Person(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;
    }
}
public class MyComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        int num = o1.name.length() - o2.name.length();//主要条件是字符长度
        return num == 0 ? o1.age - o2.age : num;//次要条件是年龄
    }
}
    private void customSort() {
        List<Person> list = new ArrayList<>();
        list.add(new Person("abcde", 13));
        list.add(new Person("abcd", 19));
        list.add(new Person("abcdef", 5));
        list.add(new Person("abcd", 15));
        System.out.println("------排序前------");
        for (Person p : list) {
            System.out.println(p.getName() + "," + p.getAge());
        }
        // 进行排序操作
        Collections.sort(list, new MyComparator());
        System.out.println("------排序后------");
        for (Person p : list) {
            System.out.println(p.getName() + "," + p.getAge());
        }
    }

打印信息:

 I/System.out: ------排序前------
 I/System.out: abcde,13
 I/System.out: abcd,19
 I/System.out: abcdef,5
 I/System.out: abcd,15
 I/System.out: ------排序后------
 I/System.out: abcd,15
 I/System.out: abcd,19
 I/System.out: abcde,13
 I/System.out: abcdef,5

总结

转自:https://www.cnblogs.com/yzssoft/p/7127894.html

上一篇下一篇

猜你喜欢

热点阅读