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 ...
随机推荐
- 对于处理datetime数据类型的一些常用方法:
datetime数据类型常用方法: 在项目中从数据库中取出数据后通常需要先绘制图像进行数据的观察,此过程中使用到的方法: 1.时间数据类似于 2022-03-23 14:21:45 可以先转换为dat ...
- 201922904李龙威 2019-2020-2 《Python程序设计》实验二报告
20192204 2019-2020-2 <Python程序设计>实验二报告 课程:<Python程序设计> 班级: 1922 姓名: 李龙威 学号:20192204 实验教师 ...
- 2.5 C++STL stack详解
文章目录 2.5.1引入 2.5.2 代码示例 2.5.3 代码运行结果 总结 2.5.1引入 stack是一种"先进后出"的容器. 不过值得注意的是stack是一种关联容器,是通 ...
- JavaWeb——基本概念
1.1 web开发: web:网页 静态web: 普通的html,css 特点:数据内容不会变化 动态web: 百度等几乎所有的网站 提供:数据内容会变化 技术栈:Servlet/JSP(Java), ...
- 嵌入式Linux应用开发完全手册之环境搭建
@ 目录 0.下载源配置 1.电脑BIOS启动虚拟化 2.linux网卡查看与IP设置 3.windows NAT虚拟网络配置 4.修改 Ubuntu 的 mountd 端口 5.vim设置 6.Mo ...
- vue2.x版本中computed和watch的使用入门详解-watch篇
前言 watch顾名思义,属于vue2.x版本中,监听和观察组件状态变化的钩子函数,常见的应用场景有监听路由变化,以及父组件传递给子组件的props数据的变化等 基本使用 在使用watch的时候,需要 ...
- Redis的安装与启动(一)
Redis是c语言开发的. 安装redis需要c语言的编译环境.如果没有gcc需要在线安装.yum install gcc-c++ 安装步骤: 第一步:redis的源码包上传到linux系统.--源码 ...
- Java 中 ConcurrentHashMap 的并发度是什么?
ConcurrentHashMap 把实际 map 划分成若干部分来实现它的可扩展性和线程安 全.这种划分是使用并发度获得的,它是 ConcurrentHashMap 类构造函数的一 个可选参数,默认 ...
- WeakHashMap 是怎么工作的?
WeakHashMap 的工作与正常的 HashMap 类似,但是使用弱引用作为 key,意思就是当 key 对象没有任何引用时,key/value 将会被回收.
- 面试问题之C++语言:如何避免内存泄漏?
转载于:https://www.php.cn/csharp-article-416104.html 1.不要手动管理内存,可以尝试在适用的情况下使用智能指针. 2.使用string而不是char*.s ...