python treemap_使用TreeMap

python treemap_使用TreeMap我们已经知道 HashMap 是一种以空间换时间的映射表 它的实现原理决定了内部的 Key 是无序的 即遍历 HashMap 的 Key 时 其顺序是不可预测的 但每个 Key 都会遍历一次且仅遍历一次 还有一种 Map 它在内部会对 Key 进行排序 这种 Map 就是 SortedMap 注意到 SortedMap 是接口 它的实现类是 TreeMap Map

我们已经知道,HashMap是一种以空间换时间的映射表,它的实现原理决定了内部的Key是无序的,即遍历HashMap的Key时,其顺序是不可预测的(但每个Key都会遍历一次且仅遍历一次)。

还有一种Map,它在内部会对Key进行排序,这种Map就是SortedMap。注意到SortedMap是接口,它的实现类是TreeMap。

┌───┐

│Map│

└───┘

┌────┴─────┐

│ │

┌───────┐ ┌─────────┐

│HashMap│ │SortedMap│

└───────┘ └─────────┘

┌─────────┐

│ TreeMap │

└─────────┘

SortedMap保证遍历时以Key的顺序来进行排序。例如,放入的Key是”apple”、”pear”、”orange”,遍历的顺序一定是”apple”、”orange”、”pear”,因为String默认按字母排序:

import java.util.*;

—-

public class Main {

public static void main(String[] args) {

Map map = new TreeMap<>();

map.put(“orange”, 1);

map.put(“apple”, 2);

map.put(“pear”, 3);

for (String key : map.keySet()) {

System.out.println(key);

}

// apple, orange, pear

}

}

使用TreeMap时,放入的Key必须实现Comparable接口。String、Integer这些类已经实现了Comparable接口,因此可以直接作为Key使用。作为Value的对象则没有任何要求。

如果作为Key的class没有实现Comparable接口,那么,必须在创建TreeMap时同时指定一个自定义排序算法:

import java.util.*;

—-

public class Main {

public static void main(String[] args) {

Map map = new TreeMap<>(new Comparator() {

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);

}

// {Person: Bob}, {Person: Lily}, {Person: Tom}

System.out.println(map.get(new Person(“Bob”))); // 2

}

}

class Person {

public String name;

Person(String name) {

this.name = name;

}

public String toString() {

return “{Person: ” + name + “}”;

}

}

注意到Comparator接口要求实现一个比较方法,它负责比较传入的两个元素a和b,如果ab,则返回正数,通常是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 map = new TreeMap<>(new Comparator() {

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”, 66), 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”, 66))); // null?

}

}

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);

}

}

在for循环中,我们确实得到了正确的顺序。但是,且慢!根据相同的Key:new Student(“Bob”, 66)进行查找时,结果为null!

这是怎么肥四?难道TreeMap有问题?遇到TreeMap工作不正常时,我们首先回顾Java编程基本规则:出现问题,不要怀疑Java标准库,要从自身代码找原因。

在这个例子中,TreeMap出现问题,原因其实出在这个Comparator上:

public int compare(Student p1, Student p2) {

return p1.score > p2.score ? -1 : 1;

}

在p1.score和p2.score不相等的时候,它的返回值是正确的,但是,在p1.score和p2.score相等的时候,它并没有返回0!这就是为什么TreeMap工作不正常的原因:TreeMap在比较两个Key是否相等时,依赖Key的compareTo()方法或者Comparator.compare()方法。在两个Key相等时,必须返回0。因此,修改代码如下:

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)也可以返回正确的比较结果。

小结

SortedMap在遍历时严格按照Key的顺序遍历,最常用的实现类是TreeMap;

作为SortedMap的Key必须实现Comparable接口,或者传入Comparator;

要严格按照compare()规范实现比较逻辑,否则,TreeMap将不能正常工作。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/230069.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午3:11
下一篇 2026年3月16日 下午3:12


相关推荐

  • win7 配置JDK环境变量

    win7 配置JDK环境变量第一步 安装 jdk 8u101 windows x64 exe 路径为默认路径 一直下一步直到完成安装 安装最好不要修改安装路径 防止自己找不到 第二步 设置环境变量 1 进入环境变量设置的方法 这里只针对 Windows7 计算机 右键 属性 高级系统设置 高级 环境变量 打开环境变量设置窗口 2 在下面的 系统环境变量 设置窗口中 点击 新建 建立 JAVA HOME

    2026年3月17日
    2
  • navicat 1146错误「建议收藏」

    navicat 1146错误「建议收藏」打开新安装的navicat后,有个test_3306的mysql连接,里面有写默认的mysql、information_schema、sys、performance_schema数据库,我以为这是没用的就删除了,之后建立自己的mysql连接后,打开连接报错1146-Table’historyhistoryperformance_schema.session_status’doesn’texist。查阅资料后了解mysql、information_schema、sys、performance_s

    2022年6月7日
    186
  • Android定时器Timer简单使用「建议收藏」

    Android定时器Timer简单使用「建议收藏」Android定时器Timer简单使用Timer简介Timer使用总结Timer简介Timer(计时器)位于java.util包下,可用于创建定时任务,任务可以安排为一次性执行,也可以定期重复执行。每个计时器对象对应一个后台线程(TimerThread)。简单理解为创建Timer对象,对应TimerThread线程循环开始从TaskQueue队列中执行一个TimerTask任务。Timer使用创建Timer对象vartimer=Timer()添加需要执行的任务//创建计

    2022年7月25日
    13
  • Maven – 解决Maven下载依赖包速度慢问题

    Maven – 解决Maven下载依赖包速度慢问题

    2021年6月29日
    69
  • C++之内联函数

    C++继承C的一个重要特性是效率,在C中保护效率的一个方法是使用宏(macro),宏的实现是使用预处理器而不是编译器,预处理器直接用宏代码替换宏调用,所以就没有了参数压栈、生成汇编语言的CALL、返回

    2021年12月19日
    52
  • 小白必看:如何无损将MBR转换成GPT磁盘?硬盘扩容提速指南

    小白必看:如何无损将MBR转换成GPT磁盘?硬盘扩容提速指南

    2026年3月16日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号