Java:Map(四)——传入Comparator对Key排序:TreeMap
对Key进行排序的Map:java.util.TreeMap
有一种Map,它在内部会对Key进行排序,这类Map称之为SortedMap。不过SortedMap是接口,它的实现类是TreeMap。
SortedMap遍历时以Key的顺序来进行排序。
例如,放入的Key是"apple"、"pear"、"orange",遍历的顺序一定是"apple"、"orange"、"pear",因为String默认按字母排序:
public class Main { public static void main(String[] args) { Map<String,Integer> map = new TreeMap<>(); map.put("orange",1); map.put("apple",2); map.put("pear",3); for(String str : map.keySet()) System.out.println(str); } } apple orange pear
使用TreeMap时,Key必须实现Comparable接口,String、Integer这些类已经实现了这个接口,因此可以直接作为Key。而Value却没有任何要求。
如果作为Key的class没有实现Comparable接口,那么在创建TreeMap时同时指定一个自定义排序算法;
一个例子
Map <Person , Integer> map =new TreeMap <> ( new Comparator<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"),3); map.put(new Person("Lily"),2); for (Person key : map.keySet()) { System.out.println(key); } // {Person: Bob}, {Person: Lily}, {Person: Tom} System.out.println(map.get(new Person("Bob"))); // 2
例如上述代码中,注意到Comparator接口要求实现一个compare()方法,它负责比较传入的两个元素a、b:
- a<b则返回负数,通常是-1;
- a=b则返回0;
- a>b返回正数,通常是1。
TreeMap内部根据比较结果对Key进行排序。
从上述代码执行结果可知,打印的Key确实是按照Comparator定义的顺序排序的。如果要根据Key查找Value,我们可以传入一个new Person( "Bob" )作为Key,它会返回对应的Integer值2。
另外,注意到Person并未覆写equals()、hashCode(),因为TreeMap不使用equals()、hashCode()。
另一个例子
我们定义一个Student类,根据score进行排序,高分在前:
import java.util.*; 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){ return p1.score > p2.score ? 1 : -1;
} } ); map.put(new Student("Tom",77),1); map.put(new Student("Bob",61),2); map.put(new Student("Lily",99),3); for(Student key : map.keySet()) System.out.println(key); System.out.println(map.get(new Student("Bob",61))); } } 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); } }
运行结果:
{Bob: score=61} {Tom: score=77} {Lily: score=99} null
在for循环中,我们确实得到了按score排序的结果。但是根据相同Key查询时,结果却为null。
原因在于,构建cmparator必须严格遵守正、负、0的规则,而在上文我们却没有实现0,即两个值相等。
修改
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; } } );
或者直接借助Integer.compare( int , int )也能返回正确的比较结果:
public int compare(Student p1 , Student p2){ return Integer.compare(p1.score,p2.score); }
小结
- SortedMap遍历时根据Key的顺序遍历,最常用的实现类是TreeMap;
- 作为SortedMap的Key必须实现Comparable接口,或者传入Comparator;这个Comparator决定了如何对Key进行排序;
- 要严格按照compare()规范实现比较逻辑返回0、正、负,否则,TreeMap不会正常工作。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· PowerShell开发游戏 · 打蜜蜂
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性