Java Map的正确使用方式
原文:https://www.liaoxuefeng.com/article/1256136507802816
正确使用Map
,只需要正确实现hashCode()
和equals()
就行了吗?
恐怕还不行。
确切地说,如果使用的是HashMap
,那么只需要正确实现hashCode()
和equals()
就够了。
但是,如果换成TreeMap
,正确实现hashCode()
和equals()
,结果并不一定正确。
代码胜于雄辩。先看作为key的class定义:
class Student implements Comparable<Student> {
final String name;
final int score;
public Student(String name, int score) {
this.name = name;
this.score = score;
}
@Override
public int hashCode() {
return Objects.hash(name, score);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof Student) {
Student o = (Student) obj;
return Objects.equals(this.name, o.name) && this.score == o.score;
}
return false;
}
@Override
public int compareTo(Student o) {
return this.score < o.score ? -1 : 1;
}
}
先用HashMap
测试:
Map<Student, Integer> map = new HashMap<>();
map.put(new Student("Michael", 99), 99);
map.put(new Student("Bob", 88), 88);
map.put(new Student("Alice", 77), 77);
System.out.println(map.get(new Student("Michael", 99)));
System.out.println(map.get(new Student("Bob", 88)));
System.out.println(map.get(new Student("Alice", 77)));
输出为99
、88
、77
,一切正常。
把HashMap
改为TreeMap
再测试:
Map<Student, Integer> map = new TreeMap<>();
输出为null
、null
、null
!
怎么肥四?
说好的接口不变,实现类随便换现在不管用了?难道是JDK的bug?
遇到这种诡异的问题,首先在心里默念三遍:
- JDK没有bug。
- JDK没有bug。
- JDK没有bug。
然后开始从自己的代码找原因。
先打开JDK的TreeMap文档,注意到这句话:
This is so because the Map interface is defined in terms of the equals operation, but a sorted map performs all key comparisons using its compareTo (or compare) method
意思是,Map
接口定义了使用equals()
判定key是否相等,但是SortedMap
却使用compareTo()
来判断key是否相等,而TreeMap
是一种SortedMap
。
所以,问题出在compareTo()
方法上:
@Override
public int compareTo(Student o) {
return this.score < o.score ? -1 : 1;
}
上面这个定义,用来排序是没问题的,但是,没法判断相等。TreeMap
根据key.compareTo(anther)==0
判断是否相等,而不是equals()
。
所以,解决问题的关键是正确实现compareTo()
,该相等的时候,必须返回0
:
@Override
public int compareTo(Student o) {
int n = Integer.compare(this.score, o.score);
return n != 0 ? n : this.name.compareTo(o.name);
}
修正代码后,再次运行,一切正常。
Java Map的正确使用方式的更多相关文章
- Java ThreadPool的正确打开方式花钱的年华 | 江南白衣(5星推荐)
线程池应对于突然增大.来不及处理的请求,无非两种应对方式: 将未完成的请求放在队列里等待 临时增加处理线程,等高峰回落后再结束临时线程 JDK的Executors.newFixedPool() 和ne ...
- map的正确删除方式
遍历删除map元素的正确方式是 for(itor = maptemplate.begin; itor != maptemplate.end(); ) { if(neederase) ...
- Java map双括号初始化方式的问题
关于Java双括号的初始化凡是确实很方便,特别是在常量文件中,无可替代.如下所示: Map map = new HashMap() { { put("Name", "Un ...
- Java流的正确关闭方式
因为流是无论如何一定要关闭的,所以要写在finally里.如下: BufferedReader reader = null; try { reader = (BufferedReader) getRe ...
- Java遍历Map的3种方式
package test; import java.util.Collection; import java.util.HashMap; import java.util.Map; import ja ...
- Redis实现分布式锁的正确使用方式(java版本)
Redis实现分布式锁的正确使用方式(java版本) 本文使用第三方开源组件Jedis实现Redis客户端,且只考虑Redis服务端单机部署的场景. 分布式锁一般有三种实现方式: 1. 数据库乐观锁: ...
- java 遍历Map的四种方式
java 遍历Map的四种方式 CreationTime--2018年7月16日16点15分 Author:Marydon 一.迭代key&value 第一种方式:迭代entrySet 1 ...
- java map遍历方式及效率
本文转载自Java Map遍历方式的选择. 只给出遍历方式及结论.测试数据可以去原文看. 如果你使用HashMap 同时遍历key和value时,keySet与entrySet方法的性能差异取决于ke ...
- Java Collection - 遍历map的几种方式
作者:zhaoguhong(赵孤鸿) 出处:http://www.cnblogs.com/zhaoguhong/ 本文版权归作者和博客园共有,转载请注明出处 ---------------- 总结 如 ...
随机推荐
- golang 基于channel封装资源池(可用于封装redis、mq连接池)
package pool import ( "errors" "io" "sync" "time" ) var ( Er ...
- 解决ViewPager与百度地图滑动冲突
一.问题描述 ViewPager中嵌套百度地图的时候会出现百度地图滑动冲突. 二.期望结果: 滑动地图的时候只有地图滑动,滑动其他区域可以切换viewpager. 三.解决方法 自定义viewpage ...
- Spring笔记4
Spring中的JdbcTemplate JdbcTemplate:他是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装. JdbcTemplate的作用:用于和数据库交互的, ...
- 利用Matlab实现PID控制仿真
该文转自博客园: https://www.cnblogs.com/kui-sdu/p/9048534.html %PID Controller clear, clc, close all; ts=0. ...
- exit status 1
- UOJ343 清华集训2017 避难所 构造、打表
传送门 玄学题 考虑构造三个数\(p_1p_2,p_1p_2,p_1p_2\)满足贪心分解会分解为\(p_1^3,p_2,p_2,p_2\),那么需要满足条件 1.\(p_1 , p_2 \in Pr ...
- Mysql字符集之utf8和utf8mb4的使用问题
Mysql之utf8和utf8mb4的区别 最近在项目中使用Mysql数据库保存emoji表情
- JAVA线程Disruptor核心链路应用(八)
import java.util.concurrent.atomic.AtomicInteger; /** * Disruptor中的 Event * @author Alienware * */ p ...
- power shell命令添加SharePoint用户组与用户(用户为域用户)
查看SharePoint用户组 Get-PnPGroup 查看某一用户组 Get-PnPGroup -Identity "用户组名" 查看某一用户组下的所有成员 Get-PnPGr ...
- Java调用WebService方法总结(1)--准备工作
WebService是一种跨编程语言.跨操作系统平台的远程调用技术,已存在很多年了,很多接口也都是通过WebService方式来发布的:本系列文章主要介绍Java调用WebService的各种方法,使 ...