HashMap与HashSet的不安全问题

HashSet的不安全问题

  • HashSet与ArrayList一样也存在不安全的问题,当多线程时也会出现ConcurrentModificationException,并发修改异常
  • 需要提出解决方案

问题

public static void main(String[] args) {Set<Integer> set = new HashSet<>();for (int i = 0; i < 30;i++) {int finalI = i;new Thread(()->{set.add(finalI);System.out.println(set);},String.valueOf(i)).start();}
}

解决方案

Set set = Collections.synchronizedSet(new HashSet());

  • 这种方式是使用工具类的方式,而不是使用JUC下的内容

Set set = new CopyOnWriteArraySet<>();

  • 与ArryList类似

  • 看看CopyOnWriteArraySet的add方法

    • private final CopyOnWriteArrayList<E> al;/**
      * Creates an empty set.*/
      public CopyOnWriteArraySet() {al = new CopyOnWriteArrayList<E>();
      }public boolean add(E e) {return al.addIfAbsent(e);
      }
      
    • public boolean addIfAbsent(E e) {Object[] snapshot = getArray();return indexOf(e, snapshot, 0, snapshot.length) >= 0 ? false :addIfAbsent(e, snapshot);
      }/*** A version of addIfAbsent using the strong hint that given* recent snapshot does not contain e.*/
      private boolean addIfAbsent(E e, Object[] snapshot) {final ReentrantLock lock = this.lock;lock.lock();try {Object[] current = getArray();int len = current.length;if (snapshot != current) {// Optimize for lost race to another addXXX operationint common = Math.min(snapshot.length, len);for (int i = 0; i < common; i++)if (current[i] != snapshot[i] && eq(e, current[i]))return false;if (indexOf(e, current, common, len) >= 0)return false;}Object[] newElements = Arrays.copyOf(current, len + 1);newElements[len] = e;setArray(newElements);return true;} finally {lock.unlock();}
      }
      
    • 从上述可以看出

    • 当创建一个CopyOnwriteArraySet时,其实就是创建了一个ArrayList

    • 因为addIfAbsent这个类用来重入锁ReetrantLock,所以他可以实现同步,并发执行

  • 为什么可以使用

  • 在这里插入图片描述

聊聊HashSet的底层

  • 是通过Map实现的,Map的key是唯一的,所以将Map的key作为HashSet的值,这样就可以实现唯一性质
public boolean add(E e) {return map.put(e, PRESENT)==null;
}

HashMap的不安全问题

  • HashMap与上述几个一样,也存在不安全的问题
HashMap<String, Integer> map = new HashMap<>();for (int i = 0; i < 10; i++) {int finalI = i;new Thread(()->{map.put(String.valueOf(finalI)+"==>", finalI);},String.valueOf(i)).start();System.out.println(map);
}
  • 会出现ConcurrentModificationException,并发修改异常

解决方案

Map<String, Integer> map = Collections.synchronizedMap(new HashMap<String, Integer>());

Map<String, Integer> map = new ConcurrentHashMap<>();

在这里插入图片描述

  • 上述是类之间的关系

HashMap的底层是什么样子的?

HashMap 的底层实现基于哈希表(Hash Table)结构,并结合了 数组 和 链表 或红黑树

  1. 数组HashMap 内部维护一个数组(通常称为“桶”或“槽”),数组的每个元素都是一个链表或红黑树的根节点。数组的大小通常是 2 的幂次方,这是为了优化哈希运算中的位运算。
  2. 哈希函数:当向 HashMap 中添加元素时,会使用哈希函数计算键(Key)的哈希值。这个哈希值会被用来确定元素应该存储在哪个桶中。通常,哈希值会对数组的长度取模(hash % array.length),以确定桶的索引
  3. 链表或红黑树:当两个或更多的键具有相同的哈希值时(这称为哈希冲突),它们会被存储在同一个桶中的链表里。在 Java 8 中,当链表长度超过一定阈值(默认为 8)时,链表会转换为红黑树,以提高查询效率。当树的大小小于一定阈值(默认为 6)时,又会退化为链表
  4. 扩容:当 HashMap 中的元素数量超过数组大小的一定比例(负载因子,默认为 0.75)时,HashMap 会进行扩容,即创建一个新的、更大的数组,并将现有元素重新哈希到新数组中。扩容是一个相对昂贵的操作,因为它涉及到重新计算所有元素的哈希值和重新分配元素。
  5. 哈希值优化:为了减少哈希冲突和提高性能,HashMap 的键对象需要实现 hashCode()equals() 方法。hashCode() 方法应返回键对象的哈希码,而 equals() 方法则用于比较两个键对象是否相等。

这是HashMap底层的数组【桶】

static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;V value;Node<K,V> next;Node(int hash, K key, V value, Node<K,V> next) {this.hash = hash;this.key = key;this.value = value;this.next = next;}public final K getKey()        { return key; }public final V getValue()      { return value; }public final String toString() { return key + "=" + value; }public final int hashCode() {return Objects.hashCode(key) ^ Objects.hashCode(value);}public final V setValue(V newValue) {V oldValue = value;value = newValue;return oldValue;}public final boolean equals(Object o) {if (o == this)return true;if (o instanceof Map.Entry) {Map.Entry<?,?> e = (Map.Entry<?,?>)o;if (Objects.equals(key, e.getKey()) &&Objects.equals(value, e.getValue()))return true;}return false;}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/815772.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

1.MMD模型动作场景镜头的导入及视频导出

界面介绍 MIKUMIKUDANCE926版本 MMD的工具栏模型骨骼帧的窗口&#xff0c;在不同时间做不同动作&#xff0c;可以在这里打帧操作时间曲线操作窗口&#xff0c;控制模型两个动作之间的过渡模型操作窗口&#xff0c;导入模型选择模型相机操作&#xff0c;控制相机远近&#xf…

[ LeetCode ] 题刷刷(Python)-第128题:最长连续序列

题目描述 给定一个未排序的整数数组 nums &#xff0c;找出数字连续的最长序列&#xff08;不要求序列元素在原数组中连续&#xff09;的长度。 示例 示例 1&#xff1a; 输入&#xff1a;nums [100,4,200,1,3,2] 输出&#xff1a;4 解释&#xff1a;最长数字连续序列是 [1, 2…

Vol.44 一个分享网站的网站,每个月8.7万访问量

哈咯&#xff0c;各位朋友好啊&#xff0c;我是欧维&#xff0c;今天要给大家分享的网址是Fuun.fun&#xff0c;奇趣网站收藏家&#xff1b; 它的网址是&#xff1a;FUUN.FUN 这是一个我经常逛的网站&#xff0c;为什么我经常逛呢&#xff1f;因为可以从中发现一些有意思的网站…

全量知识系统 程序详细设计“知识”的原则及运用

今天我们聊聊 全量知识系统&#xff08;以下简称“全知系统”&#xff09;中的“知识”的原则及运用。 全知系统“程序”的三个“计算”方面 ”用户消费功能function快照”&#xff08;局部规模scale和点击率&#xff09;&#xff0c;“客户消化能力competence画像”&#xf…

数据库-Redis(8)

目录 36.可以每秒做一次RDB快照吗? 37.AOF是写前日志还是写后日志? 38.什么是AOF重写?

上位机图像处理和嵌入式模块部署(智能硬件的开发)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 目前&#xff0c;用上位机软件虽然可以部署项目&#xff0c;但是它本身有自己的缺点&#xff0c;那就是稳定性差、价格贵。稳定性这部分&#xff0…

Linux 快问快答

如果对于找 Java 后端开发的话&#xff0c;我感觉会这几个差不多了&#xff0c;面试官应该不会问的这么详细吧。一般就问问 Linux 的几个常用的命令&#xff0c;然后做一些简单的性能排查就好了。如果面试被问到另外的问题&#xff0c;那我再补充进来&#xff0c;现在先掌握这么…

kinit 笔记

介绍&#xff1a; Kinit 是一套开箱即用的中后台解决方案&#xff0c;可以作为新项目的启动模版&#xff0c;前后端分离架构&#xff0c;开箱即用&#xff0c;在线例子&#xff1a;https://kinit.ktianc.top/login。 1. 后端Api应用安装及初始化 # 获取 git clone https://g…

Java 中命令模式,请用代码具体举例

在Java中&#xff0c;命令模式是一种行为设计模式&#xff0c;它允许将请求封装成一个对象&#xff0c;从而使得可以参数化其他对象对请求进行调用、队列化请求、或者记录请求日志&#xff0c;同时支持可撤销的操作。 下面是一个简单的示例代码&#xff0c;展示了如何使用命令模…

CMC学习系列 (8):动态力输出期间的伽马范围皮质相干性

CMC学习系列:动态力输出期间的伽马范围皮质相干性 0. 引言1. 主要贡献2. 方法3. 结果4. 讨论5. 总结欢迎来稿 论文地址&#xff1a;https://www.sciencedirect.com/science/article/abs/pii/S1053811906010238 论文题目&#xff1a;Gamma-range corticomuscular coherence duri…

【面试八股文之操作系统】

1.什么是用户态和内核态&#xff1f; 用户态和内核态是操作系统中的两种运行模式或特权级别。 用户态&#xff1a;在用户态下&#xff0c;应用程序以及用户自己编写的代码运行&#xff0c;其权限受到限制&#xff0c;不能直接访问底层系统资源和执行特权操作。用户态只能受限地…

OSPF动态路由实验(思科)

华为设备参考&#xff1a; 一&#xff0c;技术简介 OSPF&#xff08;Open Shortest Path First&#xff09;是一种内部网关协议&#xff0c;主要用于在单一自治系统内决策路由。它是一种基于链路状态的路由协议&#xff0c;通过链路状态路由算法来实现动态路由选择。 OSPF的…

D. Nene and the Mex Operator

解题思路 若选定一个区间&#xff0c;则可以构造成值全为构造方如下&#xff1a;先将区间全变为0&#xff08;若区间有0且不全为0两次&#xff08;全变为一个值后再全变为0&#xff09;&#xff0c;若没有0则一次&#xff0c;若已经全为0则0次&#xff09;保留r为0&#xff0c…

Vol.45 这个壁纸网址,功能简单,每月37.7万访问量

哈咯&#xff0c;大家好&#xff0c;我是欧维&#xff0c;今天要给大家分享的网站是&#xff1a;极简壁纸&#xff0c;一个专门做电脑壁纸的网站&#xff1b; 它的网址是&#xff1a;极简壁纸_海量电脑桌面壁纸美图_4K超高清_最潮壁纸网站 网站的壁纸质量很高&#xff0c;页面…

Open CASCADE学习|BRepOffsetAPI_DraftAngle

BRepOffsetAPI_DraftAngle 是 Open CASCADE Technology (OCCT) 中用于创建带有草图斜面的几何体的类。草图斜面是一种在零件设计中常见的特征&#xff0c;它可以在零件的表面上创建一个倾斜的面&#xff0c;通常用于便于零件的脱模或是增加零件的强度。 本例演示了如何创建一个…

【系统分析师】数据库部分

文章目录 1、数据库模式2、数据库设计过程2.1ER模型 3、关系代数 ☆5、规范化理论☆5.1 非规范存在的问题5.2 相关概念5.3范式5.3.1 第一范式-1NF5.3.2 第二范式-2NF5.2.3 第三范式5.2.4 BC范式 5.4 函数依赖分解5.4.1保持函数依赖分解5.4.2 无损分解 5.5 Armstong公理系统 6、…

策略为王股票软件源代码\StkUI\View\RealTime.cpp------分时行情界面------程序代码基本都在里面

搜索 成交... C:\Users\Administrator\Desktop\源代码\策略为王股票软件源代码\StkUI\StkUI.rc(395): MENUITEM "以成交均价为准(&A)", ID_VIEW_MAINDATAAVERAGE C:\Users\Administrator\Desktop\源代码\策略为王股票软件源代码\StkUI\StkUI…

shardingsphere从4.1.1升级到5.2.1

作为工程师都希望自己的产品能够大卖&#xff0c;而项目开发中使用的技术不可能所有都是自己写的&#xff0c;使用到的开源组件例如shardingsphere这样好的组件&#xff0c;也会随着用户量的增加而需要升级&#xff0c;没必要非得像hutool那样非得自己写一边&#xff0c;当然hu…

MySQL基础入门上篇

MySQL基础 介绍 mysql -uroot -p -h127.0.0.1 -P3306项目设计 具备数据库一定的设计能力和操作数据的能力。 数据库设计DDL 定义 操作 显示所有数据库 show databases;创建数据库 create database db02;数据库名唯一&#xff0c;不能重复。 查询是否创建成功 加入一些…

lesson02 类与对象(上)

1.类的定义 2.类的访问限定符及封装 3.类的作用域 4.类的实例化 5.类的对象的大小计算 6.类成员函数的this指针 1.类的定义 class className {//类体&#xff1a;由成员函数和成员变量组成 }; class是声明类的关键字&#xff0c;className是类的名字&#xff0c;花括号…