Java集合基础知识点复习

目录

  • Java提供的常见集合
  • List
    • ArrayList底层实现与扩容机制
    • ArrayList list=new ArrayList(10)中的list扩容几次
    • 如何实现数组和List之间的转换
      • 用Arrays.asList转List后,如果修改了数组内容,list受影响吗?List用toArray转数组后,如果修改了List内容,数组受影响吗
    • ArrayList 和 LinkedList 的区别
    • 如何解决ArrayList 和 LinkedList 不是线程安全问题
  • HashMap
    • HashMap的实现原理
    • HashMap的扩容机制
    • hashMap的寻址算法
    • 为何HashMap的数组长度一定是2的次幂?
    • hashmap在1.7的多线程死循环问题
    • HashSet与HashMap的区别
    • HashTable与HashMap的区别
    • hashmap线程安全问题

Java提供的常见集合

主要分为两类:

  • 第一个是Collection 属于单列集合,第二个是Map 属于双列集合在Collection中有两个子接口List和Set。在我们平常开发的过程中用的比较多像list接口中的实现类ArrarList和LinkedList。 在Set接口中有实现类HashSet和TreeSet。
  • 在map接口中有很多的实现类,平时比较常见的是HashMap、TreeMap,还有一个线程安全的map:ConcurrentHashMap

List

ArrayList底层实现与扩容机制

ArrayList底层是用动态的数组实现的,初始容量为0,当第一次添加数据的时候才会初始化容量为10,在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组。

在这里插入图片描述


ArrayList list=new ArrayList(10)中的list扩容几次

在ArrayList的源码中提供了一个带参数的构造方法,这个参数就是指定的集合初始长度,所以给了一个10的参数,就是指定了集合的初始长度是10,这里面并没有扩容。

第二个构造方法是无参构造函数,默认创建一个空集合


如何实现数组和List之间的转换

数组转list,可以使用jdk自动的一个工具类Arrars,里面有一个asList方法可以转换为数组
List 转数组,可以直接调用list中的toArray方法,需要给一个参数,指定数组的类型,需要指定数组的长度。


用Arrays.asList转List后,如果修改了数组内容,list受影响吗?List用toArray转数组后,如果修改了List内容,数组受影响吗

Arrays.asList转换list之后,如果修改了数组的内容,list会受影响!,因为它的底层使用的Arrays类中的一个内部类ArrayList来构造的集合,在这个集合的构造器中,把我们传入的这个集合进行了包装而已,最终指向的都是同一个内存地址
list用了toArray转数组后,如果修改了list内容,数组不会影响,当调用了toArray以后,在底层是它是进行了数组的拷贝,跟原来的元素就没啥关系了,所以即使list修改了以后,数组也不受影响


ArrayList 和 LinkedList 的区别

主要是底层使用的数据结构不一样,ArrayList 是动态数组,LinkedList 是双向链表,这也导致了它们很多不同的特点。

从操作数据效率来说

ArrayList按照下标查询的时间复杂度O(1)【内存是连续的,根据寻址公式】, LinkedList不支持下标查询查找(未知索引): ArrayList需要遍历,链表也需要链表,时间复杂度都是O(n)
ArrayList尾部插入和删除,时间复杂度是O(1);其他部分增删需要挪动数组,时间复杂度是O(n)
LinkedList头尾节点增删时间复杂度是O(1),其他都需要遍历链表,时间复杂度是O(n)

从内存空间占用来说

ArrayList底层是数组,内存连续,节省内存
LinkedList 是双向链表需要存储数据,和两个指针,更占用内存

从线程安全来说,ArrayList和LinkedList都不是线程安全的



如何解决ArrayList 和 LinkedList 不是线程安全问题

主要有两种解决方案:

  • 我们使用这个集合,优先在方法内使用,定义为局部变量,这样的话,就不会出现线程安全问题。

  • 如果非要在成员变量中使用的话,可以使用线程安全的集合来替代,但是使用同步锁属于下下策,会影响服务器性能,因为它会使并行变成串行。

    • ArrayList可以通过Collections 的 synchronizedList 方法将 ArrayList 转换成线程安全的容器后再使用。
    • LinkedList 换成ConcurrentLinkedQueue来使用

还可以使用ThreadLocal,把该属性绑定在本地线程中。



HashMap

HashMap的实现原理

JDK1.8之前采用的拉链法,数组+链表
JDK1.8之后采用数组+链表+红黑树,链表长度大于8且数组长度大于64则会从链表转化为红黑树


HashMap的扩容机制

  • 在添加元素或初始化的时候需要调用resize方法进行扩容,第一次添加数据初始化数组长度为16,以后每次扩容都是达到了扩容阈值(数组长度 * 0.75
  • 每次扩容的时候,都是扩容之前容量的2倍;扩容之后,会新创建一个数组,需要把老数组中的数据挪动到新的数组中
  • 没有hash冲突的节点,则直接使用 e.hash & (newCap - 1) 计算新数组的索引位置
  • 如果是红黑树,走红黑树的添加;如果是链表,则需要遍历链表,可能需要拆分链表,判断(e.hash & oldCap)是否为0,如果是0,该元素的位置则停留在原始位置,要么移动到原始位置+增加的数组大小这个位置上

hashMap的寻址算法

这个哈希方法首先计算出key的hashCode值,然后通过这个hash值右移16位后的二进制进行按位异或运算得到最后的hash值。
在putValue的方法中,计算数组下标的时候使用hash值与数组长度取模得到存储数据下标的位置,hashmap为了性能更好,并没有直接采用取模的方式,而是使用了数组长度-1 得到一个值,用这个值按位与运算hash值,最终得到数组的位置:e.hash & (newCap - 1)


为何HashMap的数组长度一定是2的次幂?

第一:
计算索引时效率更高:如果是 2 的 n 次幂可以使用位与运算代替取模
第二:
扩容时重新计算索引效率更高:在进行扩容时会进行判断 hash值按位与运算
旧数组长租是否 == 0 如果等于0,则把元素留在原来位置 ,否则新位置是等于旧位置的下标+旧数组长度


hashmap在1.7的多线程死循环问题

jdk7的的数据结构是:数组+链表 在数组进行扩容的时候,因为链表是头插法,在进行数据迁移的过程中,有可能导致死循环

比如说,现在有两个线程
线程一:读取到当前的hashmap数据,数据中一个链表,在准备扩容时,线程二介入

线程二也读取hashmap,直接进行扩容。因为是头插法,链表的顺序会颠倒过来。比如原来的顺序是AB,扩容后的顺序是BA,线程二执行结束。

当线程一再继续执行的时候就会出现死循环的问题。
线程一先将A移入新的链表,再将B插入到链头,由于另外一个线程的原因,B的next指向了A,所以B->A->B,形成循环。

当然,JDK 8 将扩容算法做了调整,不再将元素加入链表头(而是保持与扩容前一样的顺序),尾插法,就避免了jdk7中死循环的问题。


HashSet与HashMap的区别

HashSet底层其实是用HashMap实现存储的, HashSet封装了一系列HashMap的方法. 依靠HashMap来存储元素值,(利用hashMap的key键进行存储), 而value值默认是一个Object类型的常量 所以HashSet也不允许出现重复值, 判断标准和HashMap判断标准相同, 两个元素的hashCode相等并且通过equals()方法返回true.


HashTable与HashMap的区别

第一,数据结构不一样,hashtable是数组+链表,hashmap在1.8之后改为了数组+链表+红黑树
第二,hashtable存储数据的时候都不能为null,而hashmap是可以的
第三,hash算法不同,hashtable是用本地修饰的hashcode值,这可能导致更多的哈希冲突,从而影响性能。而hashmap经常了二次hash(可以看上面的寻址算法)
第四,扩容方式不同,hashtable是当前容量翻倍+1,hashmap是当前容量翻

第五,hashtable是线程安全的,操作数据的时候加了锁synchronized,hashmap不是线程安全的,效率更高一些


hashmap线程安全问题

hashmap不是线程安全的,推荐采用ConcurrentHashMap进行使用,它是一个线程安全的HashMap
参考这篇博客。

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

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

相关文章

一键无痕清理:高效删除Mac文件夹,释放宝贵存储空间

在当今重视隐私的时代,当转让或出借Mac电脑时,确保个人文件和敏感信息彻底清除至关重要。常规删除Mac上的文件和文件夹仅使数据看似消失,实际上它们仍驻留在硬盘上,存在被数据恢复软件找回的风险。为实现不可逆的删除效果&#xf…

Python+Vuecil笔记

Nginx 进入目录: C:\nginx-1.20.2\nginx-1.20.2 start nginx 开始 nginx -s stop 停止 nginx -s quit 退出CSS 通过标签去写css 循环展示数据 JS 点击时执行事件 Django 配置media 在seetings里面修改 STATIC_URL /static/ MEDIA_URL /upload/ MEDIA_ROOT os.pat…

文心一言指令词宝典之咨询分析篇

作者:哈哥撩编程(视频号、抖音、公众号同名) 新星计划全栈领域优秀创作者博客专家全国博客之星第四名超级个体COC上海社区主理人特约讲师谷歌亚马逊演讲嘉宾科技博主极星会首批签约作者 🏆 推荐专栏: 🏅…

探索7个MAMP本地开发环境的高效替代软件

什么是本地开发环境 本地开发环境是Web开发环境中的一种类型,它是指开发者自己的计算机上配置的一套用于开发和测试网站或应用程序的软件集合。这套环境使得开发者可以在本地计算机上构建和测试网站,而无需实时部署到服务器。 创建本地开发环境有两种方…

剪映国际版 v3.7 来了,全功能纯净,附400套离线模板下载

剪映国际版 v3.7 来了,全功能纯净,附400套离线模板下载 相比国内版 国际版不仅没有广告,所有素材和功能都是免费使用的。 CapCut是剪映的国际版本,操作和各种功能几乎和剪映一模一样, 是一款免费无限制使用的视频剪辑软件,软件…

Struts2:Action类的写法,推荐使用继承ActionSupport类的方法

文章目录 方法一:Action类是一个POJO类(简单的Java类)ActionDemo2.javastruts_demo2.xmlstruts.xml运行结果其他strutsz_demo1.xml 方法二:实现一个Action的接口ActionDemo2_2.javastruts_demo2.xml运行结果 推荐!&…

pandas(day6 图表)

一. 计算效率 1. 测量代码运行时间 %%time %%timeit 单纯计算 代码块执行的时长 %%time _sum(np.arange(6)) CPU times: total: 0 ns Wall time: 1.66 ms用于多次运行代码块并计算平均执行时间 %%timeit _sum(np.arange(6))738 ns 10.7 ns per loop (mean std. dev. of 7…

干货两个常用的 Python 模块

干货|两个常用的 Python 模块 在日常开发工作中,经常会遇到这样的一个问题:要对数据中的某个字段进行匹配,但这个字段有可能会有微小的差异。比如同样是招聘岗位的数据,里面省份一栏有的写“广西”,有的写“广西壮族自…

产品软文推广方案怎么做,媒介盒子告诉你

软文营销现在已经成为许多企业进行宣传的手段,尤其是当新品发布的时候,更需要做好产品软文推广方案,让新产品的推广更加顺利,那么产品软文推广方案怎么开始?又该怎么做好呢?接下来就让媒介盒子告诉你。 一、…

springboot之RESTful接口与Swagger

一、RESTful GET获取资源、POST新建资源、PUT更新资源、DELETE删除资源。 RESTful两大特性 1、安全性:GET请求不会引起资源本身改变。 2、幂等性:对一个接口请求和多次请求返回的资源应该一致。 2xx:成功 4xx:客户端错误。 …

东方博宜 1397. 完美的偶数?

东方博宜 1397. 完美的偶数? 解题思路: 1 读取n个数存到数组里面 2 遍历数组中的每个数:判断每个数是否为偶数位;判断每个数的每个数位是否为偶数。 细节:for循环里面定义的变量只能在for循环内使用。 在遍历数组中的数…

就业班 第二阶段(python) 2401--4.7 day3 python3 函数

八、文件操作 1、读取键盘输入 input 获取标准输入,数据类型统一为字符串 #!/usr/bin/python # -*- coding: UTF-8 -*- str input("请输入:") print("你输入的内容是: ", str) 这会产生如下的对应着输入的…

使用阿里云服务器可以做什么?太多了

阿里云服务器可以干嘛?能干啥你还不知道么!简单来讲可用来搭建网站、个人博客、企业官网、论坛、电子商务、AI、LLM大语言模型、测试环境等,阿里云百科aliyunbaike.com整理阿里云服务器的用途: 阿里云服务器活动 aliyunbaike.com…

nvm安装node方便版

直接去node官网(Index of /download/release/)下载以前版本,放到nvm的安装路径下(示例:C:\Users\Administrator\AppData\Roaming\nvm),以下图命名方式。 运行命令即可使用 如果报错npm不是外部或…

每日一题(leetcode31):下一个排列-思维

思路&#xff1a;从后往前找到第一个nums[i-1]>nums[i] 然后从后往前(len-1 -->i(包含))找到第一个大于nums[i-1]的数&#xff0c;与nums[i-1]交换&#xff0c;然后对下标区间为[i,len-1]的元素进行排序。 class Solution { public:void nextPermutation(vector<in…

ensp 通过cloud连接交换,通过本机直连telnet交换机

#连接图 #cloud配置 绑定本机一个虚拟网卡&#xff0c;勾选双向通信&#xff0c;这样就可以通过真机直接telent到交换机 #交换机配置 #需要将管理口ip配置为绑定的虚拟网卡同网段的IP&#xff0c;便于直接链接 system-view sysname s5700 undo info-center en telnet server…

Q1剧集市场复盘:2024爱优腾谁在领跑国产剧市场?

2024年Q1剧集市场的成绩单出炉了。 复盘2024年第一季度剧集市场&#xff0c;可以用“生机勃勃”四个字来形容&#xff0c;虽然和去年相比&#xff0c;今年的第一季度缺少了《狂飙》这样的头部大爆款&#xff0c;但市场大盘走势向好。 根据灯塔专业版统计&#xff0c;2024Q1剧…

算法-数论-蓝桥杯

算法-数论 1、最大公约数 def gcd(a,b):if b 0:return areturn gcd(b, a%b) # a和b的最大公约数等于b与a mod b 的最大公约数def gcd(a,b):while b ! 0:cur aa bb cur%bpassreturn a欧几里得算法 a可以表示成a kb r&#xff08;a&#xff0c;b&#xff0c;k&#xff0c…

论大数据服务化发展史

文章目录 引言正文单一指令阶段脚本化阶段用户界面操作阶段大模型AIOPS阶段总结 引言 一直想写一篇服务化相关的文章&#xff0c;那就别犹豫了现在就开始吧 正文 作为大数据基础架构工程师&#xff0c;业界也笑称“运维Boy”&#xff0c;日常工作就是在各个机器上部署以及维…

2024 年广东省职业院校技能大赛(高职组)“云计算应用”赛项样题 3

#需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件包及镜像&#xff09;或有问题的&#xff0c;可私聊博主&#xff01;&#xff01;&#xff01; #需要资源&#xff08;软件…