天天看點

Set集合之TreeSet(排序的子類)

TreeSet存儲系統定義類型(引用、直接)

與 HashSet 不同的是,TreeSet 本身屬于排序的子類:

import java.util.TreeSet;
public class TreeSetDemo {
    // 内部采用二叉樹有序存儲,此處的有序不是指按照存儲順序,而是指資料順序
    public static void main(String[] args) {
        TreeSet<String> treeSet = new TreeSet<>();
        treeSet.add("B");
        treeSet.add("C");
        treeSet.add("A");
        treeSet.add("D");
        for(String s : treeSet){
            System.out.println(s);
        }
        System.out.println((char)0);
    }
}
// 會輸出ABCD
           

雖然在增加元素的時候屬于無序的操作,但是增加之後卻可以為使用者進行排序功能的實作。

對自定義類型進行排序

TreeSet 的集合因為借用了 Comparable 接口,同時可以去除重複值,而 HashSet 雖然是 Set 接口子類,但是對于沒有複寫 Object 的 equals 和 hashCode 方法的對象,加入了 HashSet 集合中也是不能去掉重複值的。

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
/**
 * 關于 TreeSet 的排序實作,如果集合中對象是自定義的或者說其他系統定義的類沒有實作 Comparable 接口,
 * 則不能實作 TreeSet 的排序,會報類型轉換(轉向 Comparable 接口)錯誤。 換句話說要添加到 TreeSet
 * 集合中的對象的類型必須實作了 Comparable 接口。
 * 不過 TreeSet 的集合因為借用了 Comparable 接口,同時可以去除重複值(compareTo(T[] o) ),而 HashSet
 * 雖然是 Set 接口子類,但是對于沒有複寫 Object 的 equals 和 hashCode 方法的對象,加入了 HashSet 集合
 * 中也是不能去掉重複值的。
 */
public class TreeSetDemo2 {
    public static void main(String[] args) {
        TreeSet<Person> treeSet = new TreeSet<>();
        Person p1 = new Person("張三",20);
        Person p2 = new Person("李四",19);
        Person p3 = new Person("麻子",19);
        treeSet.add(p1);
        treeSet.add(p2);
        treeSet.add(p3);
        for(Person p : treeSet){
            System.out.println(p);
        }
        System.out.println("-----分割線-----");
        /** // 沒有重寫equals和hasCode方法時
         * 之前使用 Comparable 完成的對于重複元素的判斷,那麼 Set 接口定義的時候本身就是不允許重複元素的,
         * 那麼證明如果現在真的是有重複元素的話,使用 HashSet 也同樣可以進行區分。
         * 此時發現,将下面代碼的equals和hashcode方法注釋掉可以發現,并沒有去掉所謂的重複元素,也就是說之前的操作并不是真正的重複元素的判斷,而是通過
         * Comparable 接口間接完成的。
         * 如果要想判斷兩個對象是否相等,則必須使用 Object 類中的 equals()方法。
         * 從最正規的來講,如果要想判斷兩個對象是否相等,則有兩種方法可以完成: ·
         *      第一種判斷兩個對象的編碼是否一緻,這個方法需要通過 hashCode()完成,即:每個對象有唯一的編碼
         *      還需要進一步驗證對象中的每個屬性是否相等,需要通過 equals()完成。
         *    是以此時需要覆寫 Object類中的 hashCode()方法,此方法表示一個唯一的編碼,一般是通過公式計算出來的。
         */
        Set<Person> all = new HashSet<>();
        all.add(new Person("張三", 10));
        all.add(new Person("李四", 10));
        all.add(new Person("李四", 10));
        all.add(new Person("王五", 11));
        System.out.println(all);
        /**
         * 重寫equals和hasCode後,可以發現重複元素不存在了,是以如果要想去掉重複元素需要依靠 hashCode()和
         * equals()方法共同完成。
         */
    }
    /**
     * Comparable<>後的泛型控制的是抽象方法compareTo裡面的參數類型,如果不給,方法自動建立Object參數
     */
    static class Person implements Comparable<Person>{
        private String name;
        private int age;
        @Override
        public int compareTo(Person o) {
            // this 與 o比較
            // 傳回的資料:負數this小/零一樣大/正數this大
            // 将比較的規則寫在這裡
            if(this.age > o.age){
                return 1;
            }else if(this.age == o.age){
                // 因為set集合不存儲重複元素,是以當判斷兩個元素相同時,并不會進行存儲第二個元素
                return 0;
            }else{
//                return -1;
                // 如果假設年齡相等的話,按字元串進行排序。
                return this.name.compareTo(o.name);
            }
        }
        public Person(String name, int age) {
            this.name = name;
            this.age = age;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o){
                return true;
            }
            if (o == null || getClass() != o.getClass()){
                return false;
            }
            Person person = (Person) o;
            return age == person.age && Objects.equals(name, person.name);
        }

        @Override
        public int hashCode() {
            return Objects.hash(name, age);
        }

        @Override
        public String toString() {
            return "Person{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }

        public Person() {
        }

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

    }
}