Java集合中的排序方法

weixin_33912445發表於2018-09-13

1.1.1. Comparable介面(瞭解)

預設情況下,TreeSet中的元素會採用自然排序(從小到大),此時要求元素物件必須實現java.util.Comparable介面,大多數JDK自帶的類都實現了該介面,比如八大包裝類和String。

TreeSet會呼叫元素的compareTo方法來比較元素的大小關係,然後將集合元素按照升序排列。

public interface Comparable<T> {

    public int compareTo(T o);

}

比較規則,拿當前元素和另一個元素做比較:

  • this > o:返回正整數 1 ,優先順序較高

  • this < o:返回負整數 -1 ,優先順序較低

  • this == o: 返回 0 ,此時認為兩個物件為同一個物件。

此時compareTo方法返回0,則認為兩個物件是同一個物件,返回正數排前面,返回負數排後面。

如果我們自定義一個類,需要儲存到TreeSet中,此時我們需要讓該類實現Comparable介面,並覆蓋compareTo方法,在該方法編寫比較規則。

需求:按照使用者的年齡從小到大排序

class User implements java.lang.Comparable<User> {

    private String name;

    private int age;

    public User(String name, int age) {

        this.name = name;

        this.age = age;

    }

    //比較規則

    public int compareTo(User o) {

        if (this.age > o.age) {

            return 1;

        } else if (this.age < o.age) {

            return -1;

        }

        return 0;

    }

    public String toString() {

        return "User [name=" + name + ", age=" + age + "]";

    }

}

public class ComparableDemo{

    public static void main(String[] args) {

        Set<User> set = new TreeSet<>();

        set.add(new User("stef", 28));

        set.add(new User("will", 17));

        set.add(new User("allen", 15));

        set.add(new User("Lucy", 22));

        System.out.println(set);

    }

}

輸出結果:

[User [name=allen, age=15], User [name=will, age=17], User [name=Lucy, age=22], User [name=stef, age=28]]

第一步:第一個節點進去,直接作為根節點,無需比較

10465542-e17342375723314f.png
image.png

第二步:第二個節點進去和第一個節點作比較,此時的this表示第二個節點,如果compareTo返回-1,則插入節點往左邊走。

10465542-a148c242161de8a4.png
image.png

第三步:第三個節點進去和第一個節點做比較,返回-1,再和第二個節點做比較。

10465542-9e42b074aac34012.png
image.png

第四步:由於TreeSet是平衡二叉樹,如果樹不平衡,會對節點進行調整。

10465542-1b750922030e2578.png
image.png

第五步:第四個節點進去先和will比較,再和stef比較。

10465542-0828e0e6e587abf4.png
image.png

1.1.2. Comparator介面(瞭解)

TreeSet除了預設支援自然排序外,還支援自定義排序,此時需要在構建TreeSet物件時傳遞java.util.Comparator介面的實現類物件,Comparator表示比較器,裡面封裝比較規則。

public interface Comparator<T> {

    int compare(T o1, T o2);

}

此時compare方法返回0,則認為兩個物件是同一個物件,返回正數排前面,返回負數排後面。

需求:根據使用者的名字長度排序,如果名字相同按照年齡排序。

class User {

    private String name;

    private int age;

    public User(String name, int age) {

        this.name = name;

        this.age = age;

    }

    public int getAge() {

        return age;

    }

    public String getName() {

        return name;

    }

    public String toString() {

        return "User [name=" + name + ", age=" + age + "]";

    }

}

public class App {

    public static void main(String[] args) {

        Set<User> set = new TreeSet<>(**new NameLengthComparator()**);

        set.add(new User("James", 30));

        set.add(new User("Bryant", 22));

        set.add(new User("Allen", 28));

        set.add(new User("Will", 17));

        System.out.println(set);//

    }

}

class NameLengthComparatorimplements java.util.Comparator<User> {

    public int compare(User o1, User o2) {

        int ret = o1.getName().length() - o2.getName().length();

        if (ret > 0) {

            return 1;

        } else if (ret < 0) {

            return -1;

        } else {

            if (o1.getAge() > o2.getAge()) {

                return 1;

            } else if (o1.getAge() < o2.getAge()) {

                return -1;

            } else {

                return 0;

            }

        }

    }

}

輸出結果:

[User [name=Will, age=17], User [name=Allen, age=28], User [name=James, age=30], User [name=Bryant, age=22]]

小結:HashSet做等值查詢效率高,TreeSet做範圍查詢效率高,在開發中一般使用HashSet就可以了。

若要獲得最好的學習效果,需要配合對應教學視訊一起學習。需要完整教學視訊,請參看https://ke.qq.com/course/272077

相關文章