arraylist、linkedlist、hashmap、hashset

java中四种基础集合arraylist、linkedlist、hashmap、hashset,分别代表着四种基础数据结构,本文讲解四种集合数据结构的存在原因,以及优劣性

一.arraylist

1.arraylist数据模型

arraylist是四种集合中基于内存存储模型最基础的数据结构:数组结构

数组结构在对于数据的存储时,是可以根据当前节点下表加一来获取下一个节点数据,数据是有连续性,arraylist的本质就是对数组的初始化,扩容以及增删改查等一些复杂操作进行封装,arraylist的默认长度是10,扩容操作也是新建一个1.5倍当前数组长度的数组,然后将原有数据复制到新的数组中,也是针对于连续下表进行数据的增删改查

2.arraylist的优缺点

arraylist的优缺点其实就是数组模型的优缺点

由于arraylist是连续的一组内存空间,所以可以根据初始下标0加上距离目标下标的距离很快的查出已知下标的数据,比如arraylist.get(5),其实就是获取arraylist数组中初始下标后第五个下表数据,可以通过这样有规律的加减,获取相应数据。

但是又是由于arraylist数据结构必须保证这样的有序性,所以在插入或者删除的时候就需要一些额外的操作,比如在arraylist中有5个数据,我们要删除下标为3的数据,这就面临一个问题,物理的内存空间是无法通过程序去删除的,那么,要么我们给下标为3的数据赋值一个特定数据,但list集合中可以存储任何数据,没有可以永远不出现的值来供给我们赋值,那么就只能下标4的数据来填充下标3的位置,下标5数据填充下标4的位置,那如果这个arraylist长度为1万呢?我要删除下标1的数据,就会需要9999此这样的操作,势必会影响性能

那这个问题该如何解决?

二.linkedlist

在汇编或者C语言中,我们了解过指针,当中有跳转指令,比如jmp指令,可以无条件的跳转到下一个指针或者方法上,那linkedlist的数据模型理念就是根据指针跳转的方式进行存储数据,我们储存当前数据的时候,也记录下一个数据的指针,这样就形成了一个链条一样,依靠指针进行链接,指针是无序的,也就在做插入和删除的时候只要更改下一数据的指针指向就可以,但是也由于无序,所以,精确查询就会很麻烦,必须遍历整个链条,对数据进行比对才能找出需要的数据。

如果这个链条长度是1W,而我们需要的数据在第1W个,该怎么提升效率?

三.hashmap

Linkedlist查询困难的原因是遍历和不可知的长度问题,那最简单的方式是我们对有相同特定属性的链表数据进行分组,比如如果链表数据是名字,那我们就把所有姓王的分一组,姓李的分一组,将赵,王,当作相应组的查询索引,那我们就可以将一个很长的链表划分为很多小链表,再遍历小链表时,效率就会提高很多,这个小链表的索引值如何定义,再程序中,值可以是各种类型,面对不同类型进行提取相同属性做索引再开发中是不太现实的,所以我们可以把索引类型定义为字符串类型,然后对字符串进行某些类似最大公约数的计算,公约数相同的值为一组。

以k(string)-v(object)这种结构进行定义一个数据,要存入map中时,对k进行计算,然后将v存入小链表,那k以数组结构进行储存,这样就能极快的查找到小链表位置,并查出对应数据。

这样看似解决了链表长度过长问题,但是当小链表的长度也足够长,我们就需要转换hash算法,从新多key的数组进行扩容,将链表进一步再细化的划分。

那么HashMap什么时候进行扩容呢?当hashmap中的元素个数超过数组大小*loadFactor时,就会进行数组扩容,loadFactor的默认值为0.75,也就是说,默认情况下,数组大小为16,那么当hashmap中元素个数超过16*0.75=12的时候,就把数组的大小扩展为2*16=32,即扩大一倍,然后重新计算每个元素在数组中的位置,而这是一个非常消耗性能的操作,所以如果我们已经预知hashmap中元素的个数,那么预设元素的个数能够有效的提高hashmap的性能。比如说,我们有1000个元素new HashMap(1000), 但是理论上来讲new HashMap(1024)更合适,不过上面annegu已经说过,即使是1000,hashmap也自动会将其设置为1024。 但是new HashMap(1024)还不是更合适的,因为0.75*1000 < 1000, 也就是说为了让0.75 * size > 1000, 我们必须这样new HashMap(2048)才最合适,既考虑了&的问题,也避免了resize的问题。

四.hashset

arraylist,linkedlist,hashmap都可以存储重复的值,arraylist和hashmap都是由于下标或者key值不同,linkedlist由于下一个内存地址不同,那如果我们需要存储一段没有重复值的数据,那我们可以再将数据存到内存之前,对数据进行比较,如果有重复的,就不存入数据,但数据类型各种各样,我们就要有一套可以兼容所有类型的算法进行计算计算,比如将数据地址转换为二进制码,,只要转换后,再数据中没有转换后的值,我们就可将其放入,当然这事简单的计算,至于真正的hash算法,会在之后算法中讲解,这里只讲述设计思路,hashmap,对key值具有天然的计算,我们可以利用这个算法,对数据进行计算去重,所以hashset的底层储存结构是hashmap,用hashmap的key储存数据,VALUE使用固定的object填充,之所以需要填充Object而不是填充null或者直接字符串,因为再hashmap进行put的时候,成功返回null,而失败会返回失败的value值,如果填充null或者固定字符串,再某种特定情况下,无法判断put是否成功

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伤何123

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值