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 operation
                  int 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;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于 Operator 部署 Prometheus 监控 k8s 集群

目录 一、环境准备 1.1 选择版本 1.2 过滤镜像 1.3 修改 yaml 镜像 1.4 移动 *networkPolicy*.yaml 1.5 修改 service 文件 1.6 提前下载镜像并推送到私有镜像仓库 1.7 修改镜像&#xff08;可选&#xff09; 二、执行创建 三、查看 pod 状态 四、访问 prometheus、…

计算机毕业设计springboot小区物业报修管理系统m8x57

该物业报修管理系统实施的目的在于帮助物业管理企业升级员工管理、住户管理、报修问题管理等内部管理平台&#xff0c;整合物业管理企业物力和人力&#xff0c;全面服务于维修人员管理的内部管理需求,并重视需求驱动、管理创新、与业主交流等外部需求,通过物业管理企业各项资源…

【深入理解Java IO流0x09】解读Java NIO核心知识(下篇)

1. NIO简介 在开始前&#xff0c;让我们再简单回顾一下NIO。 在传统的 Java I/O 模型&#xff08;BIO&#xff09;中&#xff0c;I/O 操作是以阻塞的方式进行的。也就是说&#xff0c;当一个线程执行一个 I/O 操作时&#xff0c;它会被阻塞直到操作完成。这种阻塞模型在处理多…

第⑫讲:Ceph集群OSD扩缩容中Reblanceing数据的重分布

文章目录 1.Reblanceing数据重分布的概念2.验证Reblanceing触发的过程3.Reblanceing细节4.临时关闭Reblanceing机制 1.Reblanceing数据重分布的概念 当集群中OSD进行扩缩容操作后&#xff0c;会触发一个Reblanceing数据重分布的机制&#xff0c;简单的理解就是将扩缩容前后OSD…

服务调用-微服务小白入门(4)

背景 各个服务应用&#xff0c;有很多restful api&#xff0c;不论是用哪种方式发布&#xff0c;部署&#xff0c;注册&#xff0c;发现&#xff0c;有很多场景需要各个微服务之间进行服务的调用&#xff0c;大多时候返回的json格式响应数据多&#xff0c;如果是前端直接调用倒…

AI python

AI python 软件方面程序上的人工智能&#xff0c;和物理那种能跑机器人没关系

超聚变服务器快速收集硬件故障日志方法(iBMC)

1、使用网线直接连接服务器的Mgmt口&#xff0c;另外一端连接电脑 2、电脑随便配置一个192.168.2.101段的IP&#xff0c;除100外 3、使用以下默认信息连接IBMC&#xff0c;即可成功登录 默认连接地址&#xff1a;192.168.2.100 默认账号&#xff1a;Administrator 默认密码&am…

【Vit】Vision Transformer 入门与理解

在学习VIT之前&#xff0c;建议先把 Transformer 搞明白了&#xff1a;【transformer】入门与理解 做了那些改进&#xff1f; 看图就比较明白了&#xff0c;VIT只用了Encoder的部分&#xff0c;把每一个图片裁剪成若干子图&#xff0c;然后把一个子图flatten一下&#xff0c;…

[大模型]Langchain-Chatchat安装和使用

项目地址&#xff1a; https://github.com/chatchat-space/Langchain-Chatchat 快速上手 1. 环境配置 首先&#xff0c;确保你的机器安装了 Python 3.8 - 3.11 (我们强烈推荐使用 Python3.11)。 $ python --version Python 3.11.7接着&#xff0c;创建一个虚拟环境&#xff…

力扣HOT100 - 240. 搜索二维矩阵 II

解题思路&#xff1a; 从左下角开始&#xff0c;根据条件删除行和列。 class Solution {public boolean searchMatrix(int[][] matrix, int target) {int row matrix.length - 1;int col matrix[0].length - 1;int l 0;while (row > 0 && l < col) {if (targ…

宝宝洗衣机怎么选?四款畅销卓越婴儿洗衣机深度剖析!

近几年科技高速发展&#xff0c;我们的生活也因此变得更加便捷、健康高效。尤其是在家庭生活中&#xff0c;各种新兴家电的出现让我们的生活变得更加健康卫生。婴儿洗衣机也为现代家庭提供了极大的便捷。由于婴儿刚出生免疫力比较弱&#xff0c;所以建议婴儿的衣物尽量和大人的…

【面试八股总结】排序算法(一)

参考资料 &#xff1a;阿秀 一、冒泡排序 冒泡排序就是把小的元素往前交换或者把大的元素往后交换&#xff0c;比较相邻的两个元素&#xff0c;交换也发生在这两个元素之间。具体步骤&#xff1a; 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。对每一对…

细胞活性和细胞增殖检测试剂盒--CCK8试剂盒

Cell Counting Kit-8又称CCK-8试剂盒或者CCK8试剂盒。CCK8试剂盒基于WST-8法检测细胞的细胞活性和细胞增殖。 WST-8是MTT的升级产品&#xff0c;试剂盒的工作原理是在电子耦合试剂存在的情况下&#xff0c;可以被线粒体内的脱氢酶还原生成高度 水溶性的橙黄色的甲臜产物&#…

域权限维持—黄金票据和白金票据

黄金票据和白金票据 前言 某老哥的一次面试里问到了这个问题&#xff0c;故来做一番了解 该攻击方式在BlackHat 2014被提出&#xff0c;演讲者为Alva Duckwall & Benjamin Delpy&#xff08;gentilkiwi)进行了演示&#xff0c;该演讲提出了Kerberos协议实现过程中的设计…

Python数据分析案例42——基于Attention-BiGRU的时间序列数据预测

承接上一篇的学术缝合&#xff0c;排列组合模型&#xff0c;本次继续缝合模型演示。 Python数据分析案例41——基于CNN-BiLSTM的沪深300收盘价预测-CSDN博客 案例背景 虽然我自己基于各种循环神经网络做时间序列的预测已经做烂了.....但是还是会有很多刚读研究生或者是别的领…

2024-4-11-arm作业

汇编实现三个灯的闪烁 源代码&#xff1a; .text .global _start _start: 时钟使能LDR r0,0x50000A28ldr r1,[r0]orr r1,r1,#(0x3<<4)str r1,[r0]设置PE10输出LDR r0,0x50006000ldr r1,[r0]bic r1,r1,#(0x3<<20)orr r1,r1,#(0x1<<20)str r1,[r0]设置PE1…

TikTok如何矩阵养号?TK防关联引流系统助力TK账号安全运营

TK是 TikTok旗下的短视频社交媒体&#xff0c;平台目前是全球最火的短视频平台&#xff0c;目前全球活跃用户已经超过8亿。其中 TikTok的用户已经达到8亿。TK这款短视频社交媒体平台在海外的发展潜力非常大&#xff0c;也是国内很多人的创业目标&#xff0c;很多人都想从 TK这个…

Lua脚本使用手册(Redis篇)

Lua脚本 **简介&#xff1a;**Lua是一种功能强大的&#xff0c;高效&#xff0c;轻量级&#xff0c;可嵌入的脚本语言。它是动态类型语言&#xff0c;通过使用基于寄存器的虚拟机解释字节码运行&#xff0c;并具有增量垃圾收集的自动内存管理&#xff0c;是配置&#xff0c;脚…

【源码】2024最新海外刷单抢单平台源码/自带利息宝/理财活动/带搭建教程

源码描述&#xff1a; 前台是单语言 全开源 可二开的版本 CD&#xff1a;获取方式联系小编 微信&#xff1a;uucodes 公众号&#xff1a;资源猿

房贷还款(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h> # include <math.h>int main() {//初始化变量值&#xff1b;double m, r 0.01;float d 300000;float p 6000;//运算还款所需月份&#xff1b;m log10…