java TreeSet去重與排序入門

鴨梨山大哎發表於2020-11-08

TreeSet用途

相比於HashSet,放入TreeSet的資料是有序的.那麼這種有序是如何實現的呢?

TreeSet有序的原因

如下,插入的順序是c d a,輸出的時候是a c d,說明排序了.那麼是如何排序的呢?

public class Test {
    public static void main(String[] args) {
        TreeSet<String> ts = new TreeSet<>();
        ts.add("c");// 在add方法時就排序了
        ts.add("d");// "d".compareTo("c")
        ts.add("a");
        System.out.println(ts);// [a, c, d]
    }
}

需要深入探究add方法,可以看出是呼叫了Map的put方法.然後value為固定值PRESENT.這是一種設計模式,叫做介面卡設計模式. 以插入"d"為例,此時引數e的值為"d"

在這裡插入圖片描述
進入put方法
在這裡插入圖片描述
檢視是否有Comparator在這裡插入圖片描述
在本例中沒有,所以要用Comparable 此處可以看出Comparator的優先順序高於Comparable,實際上呼叫的是該介面下的compareTo方法.
在這裡插入圖片描述

自定義類排序

自定義的類要實現排序,就要實現Comparable介面或者實現Comparator.

Comparable決定TreeSet順序

下面這個例子實現Comparable的compareTo介面,然後無論什麼,都返回0. 此時set中就只能插入一個元素了.因為再怎麼判斷都是重複資料.

public class Test {
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person(18));
        ts.add(new Person(28));
        ts.add(new Person(8));
        ts.add(new Person(25));
        ts.add(new Person(20));
        // 由於Set不能重複,所以return 0只能輸出一個資料,重複的資料不予輸入。
        System.out.println(ts);// [18]
    }
}

class Person implements Comparable{
    private  int age;
    public Person(int age){
        this.age=age;
    }

    @Override
    public String toString() {
        return ""+age;
    }

    @Override
    public int compareTo(Object o) {
        return 0;
    }
}

下面例子實現Comparable介面的compareTo方法,並依據年齡決定TreeSet中元素的順序.

public class Test {
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<>();
        ts.add(new Person(18, "lisi"));
        ts.add(new Person(28, "wangwu"));
        ts.add(new Person(8, "xiaobai"));
        ts.add(new Person(25, "zhaosi"));
        ts.add(new Person(20, "liuneng"));
        System.out.println(ts);// [wangwu 28, zhaosi 25, liuneng 20, lisi 18, xiaobai 8]
    }
}

class Person implements Comparable {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }


    @Override
    public String toString() {
        return name + " " + age;
    }

    //依據年齡決定插入順序
    @Override
    public int compareTo(Object o) {
        if (!(o instanceof Person)) {
            throw new ClassCastException("型別不對");
        }
        Person p = (Person) o;
        return p.age - this.age;
    }
}
Comparator.決定TreeSet順序

上面例子中,如果不想用年齡來排序,想用name作為排序依據,如何做?可以在Treeset的建構函式中傳入 Comparator物件,如下


public class Test {
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<>((o1, o2) -> o1.getName().compareTo(o2.getName()));
        ts.add(new Person(18, "lisi"));
        ts.add(new Person(28, "wangwu"));
        ts.add(new Person(8, "xiaobai"));
        ts.add(new Person(25, "zhaosi"));
        ts.add(new Person(20, "liuneng"));
        System.out.println(ts);//[lisi 18, liuneng 20, wangwu 28, xiaobai 8, zhaosi 25]
    }
}

class Person implements Comparable {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public String getName() {
        return name;
    }

    @Override
    public String toString() {
        return name + " " + age;
    }

    //依據年齡決定插入順序
    @Override
    public int compareTo(Object o) {
        if (!(o instanceof Person)) {
            throw new ClassCastException("型別不對");
        }
        Person p = (Person) o;
        return p.age - this.age;
    }
}

TreeSet如何去重

treeset在排序中包含了去重,因為重複的key不會被新增到map中.

總結

  • Treeset可以去重,可以有序
  • Treeset有序依賴於實現Comparable介面或者有比較器Comparator

相關文章