Map的key是否可重复
我们都知道Map的一大特性是key唯一不可重复,可是真的是这样的吗?
我们来试验一下:

运行结果:

我们可以看到在map里有两个同样的person作为key,打破了map的key不可重复的特性。
我们平时操作map一般不会出现这样的结果,怎样操作会出现上述的现象呢?
1、首先有前提条件,作为key的person必须重写hashCode与equals这两个方法保证我们在改变person的属性之后,该person的hash值发生变化。
2、其次是我们在map中put一个以person对象作为key的元素,然后我们修改该person对象的某一个属性,再次把该person对象作为key值put到map中,就得到了上述结果。
为什么会出现上述的问题呢?
我们要明白map的数据结构以及数据是如何存储到map中的
JDK1.7 HashMap是数组+链表的结构
JDK8之后HashMap是数组+链表+红黑树的结构
tips:当然这里我们就不过多的讨论7与8结构的区别
我们在put一个元素的时候,(其余逻辑省略,这里只关注元素如何定位到数组的桶位置),先拿到key对象的hash值h1,h1无符号右移16位得到h2,
再把h1与h2进行异或运算得到h3,h3与数组的(length-1)进行与运算得到元素在数组上的最终位置

tips:如果数组长度较小的时候(大多数情况下map的长度不大),key产生的hash值如果高位变化较大很大,而地位变化很小时,
如果直接拿key的hash值与上(length-1)很容易产生hash冲突,所以无符号右移16位在异或低16位使得高混乱区域与低混乱区域做一个中和,提高hash高低位的一个随机性,减少hash冲突
上面我们讲述了map是如何把元素放入到数组中的,我们再回到上面的问题,第一次把person作为key放入map之后,修改了person的name属性之后,person的hash值发生变化,从而计算出的
桶位置也随之而改变(大概率会改变,不是绝对的)再次put到map中就得到两个相同key值的map。
那么在生产应用中我们要避免使用类似于person这样的对象作为key值存储在Map中,可以使用Integer、String这样一些不可变的对象来作为key就可以避免上述情况的发生。
插一句题外话,HashSet是无序不可重复的,它其实也存在上面的情况,原因很简单HashSet的底层就是HashMap
附HashSet相关代码截图

Map的key是否可重复的更多相关文章
- Java集合篇六:Map中key值不可重复的测试
package com.test.collection; import java.util.HashMap; import java.util.Map; //Map中key值不可重复的测试 publi ...
- java中key值可以重复的map:IdentityHashMap
在Java中,有一种key值可以重复的map,就是IdentityHashMap.在IdentityHashMap中,判断两个键值k1和 k2相等的条件是 k1 == k2 .在正常的Map 实现(如 ...
- java8 stream初试,map排序,list去重,统计重复元素个数,获取map的key集合和value集合
//定义一个100元素的集合,包含A-Z List<String> list = new LinkedList<>(); for (int i =0;i<100;i++) ...
- C++ map通过key获取value
c++的map中通过key获取value的方法 一般是value =map[key],或者另一种迭代器的方式 1.在map中,由key查找value时,首先要判断map中是否包含key. 2.如果不 ...
- map的key排序
java map的key排序吗 java为数据结构中的映射定义了一个接口java.util.Map,他实现了四个类,分别是:HashMap,HashTable,LinkedHashMapTreeMap ...
- 理解ThreadLocal —— 一个map的key
作用: 当工作于多线程中的对象使用ThreadLocal维护变量时,threadLocal为每个使用该变量的线程分配一个独立的变量副本. 接口方法: protected T initialValue( ...
- Java Map按键(Key)排序和按值(Value)排序
Map排序的方式有很多种,两种比较常用的方式:按键排序(sort by key), 按值排序(sort by value).1.按键排序jdk内置的java.util包下的TreeMap<K,V ...
- Android 对Map按key和value分别排序
一.理论准备 Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. TreeMap:基于红黑树(Red-Black tre ...
- Java Map 按Key排序和按Value排序
Map排序的方式有很多种,这里记录下自己总结的两种比较常用的方式:按键排序(sort by key), 按值排序(sort by value). 1.按键排序 jdk内置的java.util包下的Tr ...
随机推荐
- Java学习笔记:02面向对象-重写_this_super_抽象类
02面向对象-重写/this/super/抽象类 ****1.this和super 作用: this: 区分本类的成员变量和局部变量同名情况 super:区分父类的成员变量和局部变量同名情况 用法: ...
- 使用socat反向Shell多台机器
原创:打码日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 场景 很多时候,我们需要批量操作多台机器,业界一般使用Ansible来实现,但使用Ansible来操作多台机器的前提是需 ...
- RISC / CISC
RISC(精简指令集计算机)和CISC(复杂指令集计算机)是当前CPU的两种架构.它们的区别在于不同的CPU设计理念和方法. CPU架构是厂商给属于同一系列的CPU产品定的一个规范,主要目的是为了区分 ...
- Paypal标准支付对接
提醒一下,题主是在快速标准支付做到一半的时候换成了标准支付,所以该文档的快速支付大家做个参考就可以了. 一.两种支付方式 标准支付 优点:纯前端对接,简单方便,适用于非技术开发人员.个人即可用,不用花 ...
- springcloud学习03-spring cloud eureka(下)
7.配置服务提供者(生产者) 7.1.配置resources/application.yml. 值eureka.client.service-url(或serviceUrl).defaultZone是 ...
- c# / .net wFramework winform 之运行后的窗体窗口可拖动操作
学习winform 的同志们可能会有这样的提问,我运行起来的窗体或者窗口该如何实现可拖动呢?今天它来了 思路:可以给窗体增加一个进度条(progressBar控件) 全局定义这几个变量: long p ...
- sum 函数语法与应用
一.sum 函数语法: SELECT SUM(expression ) FROM tables WHERE predicates; expression 常量.列或函数,或者是算术.按位与字 ...
- uniapp小程序图片前端压缩上传
目录 1,前言 2,实现代码 1,前言 这次项目中做了一个图片上传,要求是大于2MB的就压缩成2MB一下的再上传,我这边利用了uniapp的文件接口,使用canvas做了一个压缩上传的功能,目前已上线 ...
- 在Windows环境下构建Lua 入门
在Windows环境下构建Lua 一:准备软件 1.C-compiler(TDM GCC) http://tdm-gcc.tdragon.net/download 2.Lua源代码 http:// ...
- CyclicBarrier 和 CountDownLatch 的区别 ?
1.CountDownLatch 简单的说就是一个线程等待,直到他所等待的其他线程都执 行完成并且调用 countDown()方法发出通知后,当前线程才可以继续执行. 2.cyclicBarrier ...