需要重写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. (简单) POJ 2251 Dungeon Master,BFS。

    Description You are trapped in a 3D dungeon and need to find the quickest way out! The dungeon is co ...

  2. 起步X5 的铛铛的安装部署过程

    (2017年1月)主要资料: 1.铛铛的IM Server即时通信服务使用 actor   https://github.com/actorapp/actor-platform ,开发者网站是:htt ...

  3. UVA - 129 Krypton Factor (困难的串)(回溯法)

    题意:求由字母表前L个字母组成的字典序第n小的困难串.(如果一个字符串包含两个相邻的重复子串,则称它是"容易的串",其他串称为"困难的串".) 分析:回溯时,检 ...

  4. HTML段落自动换行的样式设置

    在HTML的P标记中,默认情况下是自动换行的. 如果你的段落是由中文字符或者英文单词组成的,这基本没什么问题.但是如果你的段落是由不间断的英文字母(浏览器会认为是一个单词)组成,则默认情况下不会换行, ...

  5. iOS bug 之 H5 页面没有弹出提示框

    描述:在安卓上有提示框,但是在iOS上没有提示框. step 1: 失误,是我没有在正确的位置设置网址. step 2: 修改之后,测试页能弹出提示框,但是正式的页面没有提示框. step 3: 我输 ...

  6. iOS 之 UITextView

    _lableAssess = [[UITextView alloc] init]; [_lableAssess setFrame:CGRectMake(left2, top2, width2, siz ...

  7. 1.1.Core Data是什么(Core Data 应用程序实践指南)

    Core Data是个框架,把数据当作对象来操作. 由Core Data提供的数据对象叫托管对象(managed objecgt),而Core Data 位于程序和持久化存储区之间. 托管对象模型里有 ...

  8. PHP 递归实现层级树状展现数据

    <?php $db = mysql_connect('localhost', 'root', 'root') or die('Can\'t connect to database'); mysq ...

  9. js bool true false 比较

    .想到一个好玩的,运行如下 javascript :  if ('0') alert("'0' is true");  if ('0' == false) alert(" ...

  10. Postgresql standby(备机只读)环境搭建

    下载PostgreSQL源码包,放在任意目录 设置/etc/sysctl.conf,增加以下内容 kernel.shmmni= 4096 kernel.sem =501000 6412800000 5 ...