比较器的使用
一、TreeMap 實現排序
TreeMap是一個有序結構,TreeSet也是類似。
他們可以實現對元素的排序。TreeMap 是針對 key進行排序。
如果TreeMap的key 是Integer類型,可以無需指定任何特殊條件,默認即按照升序進行排序,如:
public static void main(String[] args) {Object value = new Object();TreeMap<Integer, Object> intMap = new TreeMap<>();intMap.put(7, value);intMap.put(4, value);intMap.put(0, value);intMap.put(10, value);System.out.println(intMap);} // 輸出: {0=java.lang.Object@4554617c, 4=java.lang.Object@4554617c, 7=java.lang.Object@4554617c, 10=java.lang.Object@4554617c}那么如果想降序,或者key不是一個 Integer類型,該如何排序?
這時我們需要指定一個比較器:
public static void main(String[] args) {Object value = new Object();TreeMap<Integer, Object> intMap = new TreeMap<>((o1, o2) -> o2 - o1);intMap.put(7, value);intMap.put(4, value);intMap.put(0, value);intMap.put(10, value);System.out.println(intMap);} // 輸出: {10=java.lang.Object@f6f4d33, 7=java.lang.Object@f6f4d33, 4=java.lang.Object@f6f4d33, 0=java.lang.Object@f6f4d33}這里有一個口訣可以快速記憶升序還是降序的比較器,我們知道比較器需要接收兩個參數 o1 和 o2,那么如果是 o1 - o2 其排序結果就是升序,如果 o2 - o1 其排序結果就是降序:
排序器升降記憶口訣:
正減升,反減降
對于一個POJO 類型,如果有一個 Integer 類型的 age 屬性,希望用 age 排序,就可以是 o1.getAge() - o2.getAge() ,這就是升序,降序就是顛倒過來。
二、不添加“重復”的 key
注意,TreeMap 通過key 的大小來判定順序,它認為的 “重復” key 指的是大小比較相等的key,如果相等,便不會重復添加元素,這與HashMap 覆蓋舊值是有區別的。
public static void main(String[] args) {Student s1 = new Student(1, "s1", 24);Student s2 = new Student(2, "s2", 30);Student s3 = new Student(3, "s3", 21);Student s4 = new Student(4, "s3", 21);// TreeMap通過 key來進行排序,如果是可比較類型,直接排序// 如果不是可比較類型,需要令該類型實現Comparable接口,或構造器中指定排序器TreeMap<Student, String> stuMap = new TreeMap<>((o1, o2) -> o1.getAge() - o2.getAge());Comparator<? super Student> comparator = stuMap.comparator();stuMap.put(s2, s2.getName());stuMap.put(s3, s3.getName());stuMap.put(s1, s1.getName());stuMap.put(s4, s4.getName());System.out.println(stuMap);}輸出結果:
{Student{id=3, name='s3', age=21}=s3, Student{id=1, name='s1', age=24}=s1, Student{id=2, name='s2', age=30}=s2}可以看到由于 age = 21 的Student有s3 和 s4,但卻沒有添加 s4。
如果“重復”了,卻又想保留“重復”元素,原因 它們雖然排序屬性相等,但并不是完全相同的兩個對象,該如何做?
可以使用hashCode(但是存在沖突的風險),或直接使用內存地址來進一步比較。
三、比較器優先
對于POJO 實現了?Comparable 的情況,我們需要實現它的 compareTo 方法:
class Student implements Comparable<Student> {private Integer id;private String name;private Integer age;@Overridepublic int compareTo(Student o) {return this.age - o.getAge();}// 構造器和 getter、setter }那么 o1 就是當前 this 對象,o2 就是參數對象,同樣遵循 “正減升,反減降”的口訣。
不過如果同時指定了排序器和 Comparable ,而這兩種邏輯又存在沖突,該如何選擇呢?
答案是比較器優先,原因是比較器的位置更接近客戶代碼,在排序前指定排序規則,要比類定義時指定排序規則更加明確,因此 TreeMap 一類有序結構都是按照排序器優先的原則來排序的。
?
?
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
- 上一篇: python函数应用_python 函数
- 下一篇: Android DDMS的打开以及查看手