HashMap是一种以空间换时间的映射表,它的实现原理决定了内部的Key是无序的,即遍历HashMap的Key时, 其顺序是不可预测的(但每个Key都会遍历一次且仅遍历一次)
还有一种Map,它在内部会对Key进行排序,这种Map 就是SortedMap。注意到SortedMap是接口,它的实现类是TreeMap。**SortedMap**保证遍历时以Key的顺序来进行排序。例如,放入Key是 “apple”,”pear”,”orange”,遍历的顺序一定是**apple 、orange、pear**,因为**String**默认按字母排序。
使用TreeMap时,放入的Key必须实现Comparable接口。String、Integer这些类已经实现了Comparable接口,因此可以直接作为Key使用。作为Value对象则没有任何要求。
如果作为Key的class没有实现Comparable接口,那么,必须在创建TreeMap时同时指定一个自定义排序算法
public class Main{public static void main(String[] args){Map<Person,Integer> map = nwe TreeMap<>(new Comparaotr<Person>(){public int compare(Person p1, Person p2){return p1.name.compareTo(p2.name);}});map.put(new Person("Tom"), 1);map.put(new Person("Bob"),2);map.put(new Person("Lily"),3);for (Person key : map.keySet()){System.out.println(key);}System.out.println(map.get(new Person("Bob")));}}class Person {public String name;Person(String name){this.name = name;}public String toString() {return "{Person: "+ name + "}";}}
Map接口定义了使用equals()判定key是否相等,但是SortedMap却使用compareTo()来判断key是否相等,而TreeMap是一种SortedMap。
注意到Comparator接口要求实现一个比较方法,它负责比较传入的两个元素a和b,如果 a<b,则返回负数,通常是-1,如果a==b 则返回0,如果a>b,则返回正数,通常是1。TreeMap内部根据比较结果对key进行排序。
从上述代码执行结果可知,打印的Key确实是按照Comparator定义的顺序排序的。
另外,注意到Person类并未覆写equals()和hashCode(),因为TreeMap不使用equals()和hashCode()。
定义Student类,并用分数score进行排序,高分在前
public class Main{
public static void main(String[] args){
Map<Student, Integer> map = new TreeMap<>(new Comparator<Student>(){
public int compare(Student p1,Student p2){
if(p1.score == p2.score){
return 0;
}
return p1.score > p2.score ? -1 : 1;
}
});
map.put(new Student("xiaoming",99),1);
map.put(new Student("hanmeimei",100),2);
map.put(new Student("lilei",98),3);
for(Student s : map.keySet()){
System.out.println(s);
}
System.out.println(new Student("hanmeimei",100));
}
}
class Student {
public String name;
public int score;
Student(String name, int score) {
this.name = name;
this.score = score;
}
public String toString() {return String.format("{%s: score=%d}", name, score); }
}
TreeMap在比较两个Key是否相等时,依赖Key的CompareTo()方法或者Comparator.compare()方法。在两个Key相等时,必须返回0,或者借助Integer.compare(int, int)也可以返回正确的比较结果。
小结
SortedMap在遍历时严格按照Key的顺序遍历,最常用的实现类是TreeMap
作为SortedMap的Key必须实现Comparable接口,或者传入Comparator。
要严格按照compare()规范实现比较逻辑,否则,TreeMap将不能正常工作。
