Comparable和Comparator的區別

1.  Comparable---接口(集合中元素實現此接口,元素具有可比性)

  Comparable可以認爲是一個內比較器,實現了Comparable接口的類有一個特點,就是這些類是可以和自己比較的,至於具體和另一個實現了Comparable接口的類如何比較,則依賴compareTo方法的實現,compareTo方法也被稱爲自然比較方法。如果開發者add進入一個Collection的對象想要Collections的sort方法幫你自動進行排序的話,那麼這個對象必須實現Comparable接口。compareTo(Object o)方法的返回值是int,且此方法只有一個參數,返回值有三種情況:

1、返回正整數

2、返回0

3、返回負整數

  可以這麼理解:返回1表示當前元素排在與之對比的元素後面,返回-1表示當前元素排在與之對比的元素前面,返回0表示不排序(按其原順序排列)。(其實並不是1,-1,0;只要是正數負數和0就可以進行區分)。

  元素自身可以理解爲基準,而參數上的obj可以理解爲與之對比的元素。

1.比如我們想比較人的時候按年齡倒序排列

  思路:實現上面接口,如果與之對比的元素年齡比他大,排在他前面(返回負數),否則排在他後面(返回正數)。

例如:

 

public class Person implements Comparable<Person> {

    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        if(this.age > o.getAge()){//返回負數表示比他大的排在他前面
            return -1;
        }
        if(this.age < o.getAge()){//返回整數表示比他小的排在他後面
            return 1;
        }
        return 0;
    }

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

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

}

測試:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class Test1 {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person(20, "張三"));
        list.add(new Person(22, "李四"));
        list.add(new Person(19, "王五"));
        list.add(new Person(19, "張是"));
        list.add(new Person(17, "開發"));
        list.add(new Person(29, "看"));
        
        Collections.sort(list);
        for(Person p : list){
            System.out.println(p);
        }
    }
}

結果:

Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=張三]
Person [age=19, name=王五]
Person [age=19, name=張是]
Person [age=17, name=開發]

 

2.按照上面的思路我們寫一個按年齡正序排列

修改上面的compareTo方法:

 @Override
    public int compareTo(Person o) {
        if(this.age > o.getAge()){//返回正數表示比他大的排在他後面
            return 10;
        }
        if(this.age < o.getAge()){//返回負數表示比他小的排在他前面
            return -1;
        }
        return 0;
    }

測試代碼還是上面代碼,查看結果:

Person [age=17, name=開發]
Person [age=19, name=王五]
Person [age=19, name=張是]
Person [age=20, name=張三]
Person [age=22, name=李四]
Person [age=29, name=看]

3.將自身具有可比性的元素存入TreeSet或者TreeMap進行查看(TreeSet會自動將元素排序,元素作爲key的時候TreeMap會根據key排序)

public class Person implements Comparable<Person> {

    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int compareTo(Person o) {
        if(this.age > o.getAge()){//返回負數表示比他大的排在他前面
            return -1;
        }
        if(this.age < o.getAge()){//返回整數表示比他小的排在他後面
            return 1;
        }
        return 0;
    }

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

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

}

測試代碼:

package cn.qlq.test;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;


public class TreeSetTest {
    public static void main(String[] args) {
        Set<Person> list = new TreeSet<>();
        list.add(new Person(20, "張三"));
        list.add(new Person(22, "李四"));
        list.add(new Person(19, "王五"));
        list.add(new Person(19, "張是"));
        list.add(new Person(17, "開發"));
        list.add(new Person(29, "看"));
        
        for(Person p : list){
            System.out.println(p);
        }
        System.out.println("-----------------------------");
        
        //作爲key會將key排序
        Map map = new TreeMap();
        map.put(new Person(20, "張三"), "1");
        map.put(new Person(22, "李四"), "2");
        map.put(new Person(19, "張三"), "3");
        map.put(new Person(25, "哇塞"), "4");
        for(Object key :map.keySet()){
            System.out.println(key+"\t"+map.get(key));
        }
        
        System.out.println("-----------------------------");
        //作爲value無效
        Map map2 = new TreeMap();
        map2.put("1",new Person(20, "張三"));
        map2.put("2",new Person(22, "李四"));
        map2.put("3",new Person(19, "張三"));
        map2.put("4",new Person(25, "哇塞"));
        for(Object key :map2.keySet()){
            System.out.println(key+"\t"+map2.get(key));
        }
    }
}

結果:

Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=張三]
Person [age=19, name=王五]
Person [age=17, name=開發]
-----------------------------
Person [age=25, name=哇塞] 4
Person [age=22, name=李四] 2
Person [age=20, name=張三] 1
Person [age=19, name=張三] 3
-----------------------------
1 Person [age=20, name=張三]
2 Person [age=22, name=李四]
3 Person [age=19, name=張三]
4 Person [age=25, name=哇塞]

 

2.  Comparator---接口(可以理解爲比較器,給集合傳遞比較器集合具有可比性)

  Comparator相當於外部比較器,其作爲參數傳給具有可比性的集合,使集合具有可比性。比如:      TreeSet ts = new TreeSet(new MyComparator());   比較器需要重寫compareTo(Object o1,Object o2)方法,返回值也是下面三個值:

1、返回正整數

2、返回0

3、返回負整數

  可以這麼理解:返回1表示當前元素排在與之對比的元素後面,返回-1表示當前元素排在與之對比的元素前面,返回0表示不排序(按其原順序排列)。(其實並不是1,-1,0;只要是正數負數和0就可以進行區分)

   compareTo(Object o1,Object o2)方法的第一個參數可以理解爲基準,而參數上的第二個參數可以理解爲與之對比的元素。

1.比如我們想比較人的時候按年齡倒序排列

public class Person{

    private int age;
    private String name;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

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

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

}

比較器類:(可以理解爲第一個參數是基準,第二個參數是與之對比的元素,返回-1表示基準排在與之對比元素前面,返回1表示基準在與之對比的元素後面)

import java.util.Comparator;

public class PersonComparator implements Comparator<Person> {

    /**
     * 第一個參數可以理解爲基準,第二個是與之比較多元素 。返回負數表示排在其前面,返回正數表示排在其後面
     */
    @Override
    public int compare(Person o1, Person o2) {
        if (o1.getAge() > o2.getAge()) {// 返回正數表示比他大的排在他後面
            return -1;
        }
        if (o1.getAge() < o2.getAge()) {
            return 1;
        }
        return 0;
    }

}

測試代碼:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;


public class Test1 {
    public static void main(String[] args) {
        List<Person> list = new ArrayList<>();
        list.add(new Person(20, "張三"));
        list.add(new Person(22, "李四"));
        list.add(new Person(19, "王五"));
        list.add(new Person(19, "張是"));
        list.add(new Person(17, "開發"));
        list.add(new Person(29, "看"));
        
        Collections.sort(list,new PersonComparator());
        for(Person p : list){
            System.out.println(p);
        }
    }
}

結果:

Person [age=29, name=看]
Person [age=22, name=李四]
Person [age=20, name=張三]
Person [age=19, name=王五]
Person [age=19, name=張是]
Person [age=17, name=開發]

2.將一個比較器傳入TreeSet或者TreeMap是集合有序,或者TreeMap的key值有序(也就是TreeMap排序是將key排序)

  TreeSet中的元素會自動排序,根據傳下來的比較器對裏面的元素進行排序。TreeMap傳入比較器的話是元素作爲key纔可以排序,如果傳入比較器但是key不是比較器指定的元素會報錯。。。。。。。

比較器:

package cn.qlq.test;

import java.util.Comparator;

public class PersonComparator implements Comparator<Person> {

    /**
     * 第一個參數可以理解爲基準,第二個是與之比較多元素 。返回負數表示排在其前面,返回正數表示排在其後面
     */
    @Override
    public int compare(Person o1, Person o2) {
        if (o1.getAge() > o2.getAge()) {// 返回正數表示比他大的排在他後面
            return 10;
        }
        if (o1.getAge() < o2.getAge()) {
            return -10;
        }
        return 0;
    }

}

測試代碼:

package cn.qlq.test;

import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;


public class TreeSetTest {
    public static void main(String[] args) {
        Set<Person> list = new TreeSet<>(new PersonComparator());
        list.add(new Person(20, "張三"));
        list.add(new Person(22, "李四"));
        list.add(new Person(19, "王五"));
        list.add(new Person(19, "張是"));
        list.add(new Person(17, "開發"));
        list.add(new Person(29, "看"));
        
        for(Person p : list){
            System.out.println(p);
        }
        System.out.println("-----------------------------");
        
        //作爲key不會報錯,會將key排序
        Map map = new TreeMap(new PersonComparator());
        map.put(new Person(20, "張三"), "1");
        map.put(new Person(22, "李四"), "2");
        map.put(new Person(19, "張三"), "3");
        map.put(new Person(25, "哇塞"), "4");
        for(Object key :map.keySet()){
            System.out.println(key+"\t"+map.get(key));
        }
        
        //作爲value報錯
        Map map2 = new TreeMap(new PersonComparator());
        map2.put("1",new Person(20, "張三"));
        map2.put("2",new Person(22, "李四"));
        map2.put("3",new Person(19, "張三"));
        map2.put("4",new Person(25, "哇塞"));
        for(Object key :map2.keySet()){
            System.out.println(key+"\t"+map2.get(key));
        }
    }
}

結果:

Person [age=17, name=開發]
Person [age=19, name=王五]
Person [age=20, name=張三]
Person [age=22, name=李四]
Person [age=29, name=看]
-----------------------------
Person [age=19, name=張三] 3
Person [age=20, name=張三] 1
Person [age=22, name=李四] 2
Person [age=25, name=哇塞] 4
-----------------------------
Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to cn.qlq.test.Person
at cn.qlq.test.PersonComparator.compare(PersonComparator.java:1)
at java.util.TreeMap.compare(Unknown Source)
at java.util.TreeMap.put(Unknown Source)
at cn.qlq.test.TreeSetTest.main(TreeSetTest.java:37)

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章