需要重写hashCode()和equals()方法才可以实现自定义键在HashMap中的查找。

public class PhoneNumber
{
private int prefix; //区号
private int phoneNumber; //电话号 public PhoneNumber(int prefix, int phoneNumber)
{
this.prefix = prefix;
this.phoneNumber = phoneNumber;
}
}
import java.util.HashMap;

public class Test1
{
public static void main(String[] args)
{
HashMap<PhoneNumber, String> map = new HashMap<>(); map.put(new PhoneNumber(027, 12345678), "zhangsan");
map.put(new PhoneNumber(027, 22222222), "lisi");
map.put(new PhoneNumber(027, 33333333), "wangwu");
map.put(new PhoneNumber(027, 33333333), "abc"); System.out.println(map.toString()); System.out.println(map.get(new PhoneNumber(027, 12345678)));
System.out.println(map.get(new PhoneNumber(027, 22222222)));
System.out.println(map.get(new PhoneNumber(027, 33333333)));
}
}

运行结果为:

{package1.PhoneNumber@74a14482=zhangsan, package1.PhoneNumber@677327b6=wangwu, package1.PhoneNumber@1540e19d=lisi, package1.PhoneNumber@14ae5a5=abc}

null

null

null

从中我们可以看到出现了两个问题:

  • new PhoneNumber(027, 33333333)这个键被添加了两次,但是在HashMap中wangwu和abc同时存在了
  • 使用get方法取得的值均为null

正确的方法就是直接对PhoneNumber类进行修改,覆盖equals和hashCode方法,修改后的PhoneNumber类如下:

public class PhoneNumber
{
private int prefix; //区号
private int phoneNumber; //电话号 public PhoneNumber(int prefix, int phoneNumber)
{
this.prefix = prefix;
this.phoneNumber = phoneNumber;
} @Override
public boolean equals(Object o)
{
if(this == o)
{
return true;
}
if(!(o instanceof PhoneNumber))
{
return false;
}
PhoneNumber pn = (PhoneNumber)o;
return pn.prefix == prefix && pn.phoneNumber == phoneNumber;
} @Override
public int hashCode()
{
int result = 17;
result = 31 * result + prefix;
result = 31 * result + phoneNumber;
return result;
}
}

重新执行上述函数,结果为:

{package1.PhoneNumber@1fce2ef=abc, package1.PhoneNumber@bca3e8=zhangsan, package1.PhoneNumber@1535828=lisi}

zhangsan

lisi

abc

可以看到,之前出的错误都被改正了

在HashMap中,查找key的比较顺序为:

  1. 计算对象的HashCode,看在表中是否存在
  2. 检查HashCode位置中的对象是否与当前对象相等

以上使用计算HashCode的方法在effective java第九点中提到:

  • 对于对象中每个关键域f,为该域计算int类型的散列码c,result = 31 * result + c

Java用自定义的类型作为HashMap的key的更多相关文章

  1. 一个关于自定义类型作为HashMap的key的问题

    在之前的项目需要用到以自定义类型作为HashMap的key,遇到一个问题:如果修改了已经存储在HashMap中的实例,会发生什么情况呢?用一段代码来试验: import java.util.HashM ...

  2. java自定义类型 作为HashMap中的Key值 (Pair<V,K>为例)

    由于是自定义类型,所以HashMap中的equals()方法和hashCode()方法都需要自定义覆盖. 不然内容相同的对象对应的hashCode会不同,无法发挥算法的正常功能,覆盖equals方法, ...

  3. JAVA - 如果hashMap的key是一个自定义的类,怎么办?

    JAVA - 如果hashMap的key是一个自定义的类,怎么办? 使用HashMap,如果key是自定义的类,就必须重写hashcode()和equals().

  4. 【java】学习路径26-泛型,集合使用自定义的类型

    接着上一节的内容,上一节我们使用到了ArrayList.Vector.LinkedList三个集合类型. 但是目前我们有一个问题:如果集合中存储的是Integer类型的数据(int的引用类型),那我们 ...

  5. java容器类2:Map及HashMap深入解读

    Java的编程过程中经常会和Map打交道,现在我们来一起了解一下Map的底层实现,其中的思想结构对我们平时接口设计和编程也有一定借鉴作用.(以下接口分析都是以jdk1.8源码为参考依据) 1. Map ...

  6. Java集合类源码解析:HashMap (基于JDK1.8)

    目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...

  7. Java编程的逻辑 (40) - 剖析HashMap

    本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...

  8. 全面解读Java中的枚举类型enum的使用

    这篇文章主要介绍了Java中的枚举类型enum的使用,开始之前先讲解了枚举的用处,然后还举了枚举在操作数据库时的实例,需要的朋友可以参考下 关于枚举 大多数地方写的枚举都是给一个枚举然后例子就开始sw ...

  9. Java中的集合类型体系(一)

    Java中的集合类型体系(一) 提问:为什么需要集合? 通常情况下,程序需要根据运行时才知道创建了多少对象.若非程序运行时,而在开发阶段,我们并不知道创建了多少对象,甚至不知道对象的准确类型,为了满足 ...

随机推荐

  1. [Cocos2d-x]Lua 资源热更新

    什么是热更新 所谓的热更新,指的是客户端的更新. 大致的流程是,客户端在启动后访问更新的URL接口,根据更新接口的反馈,下载更新资源,然后使用新的资源启动客户端,或者直接使用新资源不重启客户端. 热更 ...

  2. mysql基础-- 一条请求执行多条SQL语句

    最近做一个数据库初始化工具的时候发现了这个问题,就是在一个Statement中执行一条SQL语句的时候可以正确执行,如果同时执行多条,就会报SQL语法错误,伤透了脑筋. 经过网上查找,发现有两种解决办 ...

  3. php中使用mysql_fetch_object向页面输出结果,总结!

    public function selectResultByThird() { if ((!empty ($_REQUEST["bigname"])) && (!e ...

  4. 微信小程序下拉刷新和上拉加载

    小程序知识点二 1.上拉加载和下拉刷新 Wxml文件 <scroll-view scroll-top="{{scrollTop}}" scroll-y="true& ...

  5. LPC1788的外部中断和GPIO中断

    首先是gpio中断,这一点和1768不同,1768使用的中断时和eint3共用中断通道,到了1788,专门为gpio开辟了中断 #ifndef __JOYPAD_H_ #define __JOYPAD ...

  6. uoj#38. 【清华集训2014】奇数国【欧拉函数】

     number⋅x+product⋅y=1  有整数x,y解的条件是gcd(number, product) == 1. product用线段树维护一下,然后现学了个欧拉函数. 可以这样假如x = p ...

  7. 浅谈一个网页打开的全过程(涉及DNS、CDN、Nginx负载均衡等)

    1.概要 从用户在浏览器输入域名开始,到web页面加载完毕,这是一个说复杂不复杂,说简单不简单的过程,下文暂且把这个过程称作网页加载过程.下面我将依靠自己的经验,总结一下整个过程.如有错漏,欢迎指正. ...

  8. TCP/IP 标志位 SYN ACK RST UTG PSH FIN

    三次握手:发送端发送一个SYN=1,ACK=0标志的数据包给接收端,请求进行连接,这是第一次握手:接收端收到请求并且允许连接的话,就会发送一个 SYN=1,ACK=1标志的数据包给发送端,告诉它,可以 ...

  9. 两台机子的repcached Memcache 的安装与实验

    安装memcached前先要确定系统是否安装了gcc: 1.解压安装包: tar -zxf memcached-1.2.8-repcached-2.2.tar.gz 2.编译: 系统应安装了libev ...

  10. poj 3641 ——2016——3——15

    传送门:http://poj.org/problem?id=3461 题目大意:给你两个字符串p和s,求出p在s中出现的次数. 题解:这一眼看过去就知道是KMP,作为模板来写是最好不过了.... 这道 ...