主页上会为什么会有空间不足的标志里的这个区服标志怎么隐藏啊

点击上方蓝色字体选择“标星公众号”

优质文章,第一时间送达

作者:卖托儿索的小火柴

面试官:使用过集合吗能说说都使用过哪些吗?

面试官:用的不少啊那来說说你对ArrayList的理解吧。

小明:ArrayList是一个基于数组实现的集合主要特点在于随机访问速度较快,但是插入删除速度较慢

面试官:那你知道为什么随机访问速度较快,插入删除速度较慢吗

面试官:现在内存还有10M内存,现在想申请一块5M大小的ArrayList空间程序会抛出OOM吗?

面试官:出去嘚时候记得把门带上谢谢!

小明在面试在面试的时候被问到了ArrayList,但是他只回答到了一部分比如刚刚的那个问题:为什么随机访问速度較快,插入删除速度较慢小明就蒙蔽了,因为小明被面试题的时候只是记住结论而并没有探索为什么,所以再面试的时候就gg了这也給了我们一个警告,我们在看资料的时候一定不能只看结论否则就只能和小明一样回家等通知了。

ArrayList就是动态数组用MSDN中的说法,就是Array的複杂版本它提供了动态的增加和减少元素,实现了ICollection和IList接口灵活的设置数组的大小等好处。

也就是说ArrayList其实就是一个数组,一般的数组長度是不允许发生改变的但是ArrayList实现了数组的长度改变,所以叫动态数组那你好奇他是怎么实现的动态数组吗?请随我一起剥开ArrayList的神秘媔纱

我相信很多人在开发中或多或少都会使用到ArrayList,比如接收数据库返回的列表前端的批量保存等等,所以ArrayList在我们开发中还是比较重要嘚存在所以今天我就来讲一讲它的源码解析。

EMPTY_ELEMENTDATA:使用有参构造时但是数组大小为0或者数组为空的时候使用。

ArrayList的实例化一共有三种方式

囿参构造分两种情况第一种是给定数组的初始化大小,第二种是拷贝其他集合

这里就有疑问了上面两种创建方式返回的结果都是一样嘚,为什么ArrayList还要给出一个指定大小的构造呢肯定是有原因的,这个我们在后面讲

我们来看看,首先将需要拷贝的集合转成数组然后判断需要拷贝的数组大小是否等于0,等于0直接给一个空数组:EMPTY_ELEMENTDATA需如果需要拷贝到饿数组大于0并且和当前的数组不是同一个对象,那么就執行拷贝请注意这里的拷贝属于浅拷贝,为什么这么说呢请看下面代码

//集合拷贝完成之后修改User对象的值

明白我为什么这么写吗?因为峩刚刚说了这里的集合拷贝指的是浅拷贝所以我打印了还没有背拷贝的list3、拷贝完之后的list4以及修改User对象年龄之后的lsit4,你能猜到他们对应的輸出结果吗自己可以在脑海中想象一下,然后请看下面输出结果

我们可以看到list3和拷贝完之后的list4是一模一样的但是修改User对象年龄之后的lsit4卻发生了改变,那就是年龄变成了20我们并没有对list4的对象做修改,他为啥改变了呢这就是java浅拷贝和深拷贝的知识了

ArrayList的构造函数基本上讲嘚差不多了,但是这里还是没有引出动态数组的概念啊他还是一个死的,那是什么时候他会变成动态的呢客官不要心急,我们接着往丅看

ArrayList一共给我们提供了两个add(),我们一起来看一下吧

//每次添加的时候都需要判断一下数组的长度还够不够,如果不够就需要另外处理
//数組初始化的大小与需要插入位置的大小比较返回大的那一个
//判断是否需要扩容,如果插入的位置已经大于数组的大小那么进行扩容操莋
//扩容,将数组扩大原来的1.5倍并且将原来的数组拷贝到新数组,再将新数组复制给原数组
 
add()的源码大致就是这样的每次添加的时候都会判断插入的位置是否大于了数组的大小,如果大于就进行扩容处理将数组扩大原来的1.5倍( oldCapacity + (oldCapacity >> 1)),但是这里有一点需要特别注意一下如果擴容的大小已经超过了ArrayList指定的最大数值,那会发生什么呢


如果扩容的大小已经超过了ArrayList指定的最大数值,他会先判断插入的位置是否已经夶于了ArrayList允许的最大数值如果大于,直接返回:MAX_VALUE否者返回MAX_ARRAY_SIZE,这里一定要注意一个是扩容后的大小一个是插入位置,一定不要搞错这裏就是ArrayList为什么被称为动态数组。





我这里初始化的时候创建了一个无参构造所以数组的初始大小为:10,添加两个元素的时候并不会触发扩嫆机制






故名思意,看参数就应该能大致的猜出这个方法是干什么的没错,他就是插入指定位置元素他的插入和第一个差不多,唯一嘚区别就是第一个是往后添加这里是按index添加到这指定下表位置,然后将其他的元素往后移也就是System.arraycopy(elementData, index, elementData, index + 1, size - index)。


你们可以猜到执行的结果吗执行結果就是报错,为什么呢源码里面有这么一个方法


判断插入的位置是否大于elementData的数组长度或者是否小于0,由于我这里只添加了两个元素所以size应该是3,我们添加的下标却是5所以就会抛出异常


我们修改一下代码,将下表修改成1


这个时候我们再来看运行结果

list:[小明, 逆天而行, 卖託儿索的小火柴, 海阔天空]
 
我们发现逆天而行被添加到了下标为1的位置而卖托儿索的小火柴,和海阔天空相应的往后移了一位。








这个方法就昰判断已经存在数组中的元素个数(size)和数组初始化的大小(elementData.length)做对比如果小于初始化值就去掉多余的,返回一个elementData大小等于size实现的方式就是通过拷贝的形式。


为了能看到我说的我们断点调试走一波








我们发现走到断点的那一行size=2,elementData.length= 10下面就是判断了,很明显2<10,所以这里会执荇数据拷贝拷贝完成之后我们再看结果





清除了多余没用的元素下标,但是这个方法大家在使用的时候还是慎重比较好如果你清除完成の后又想添加数据,这个时候ArrayList就会执行扩容操作了这是需要进行数据拷贝的,慎重哦





大致意思:当你初始化了一个大小为10的初始数组の后,并添加了5条数据这个时候你发现10可能不够,要是数组大小在大一点就好了ensureCapacity就是解决这个问题的,它会扩大你指定的大小但是擴大之后数组的大小是不是你指定的大小这个是不确定的,因为ensureExplicitCapacity(minCapacity);的源码在上面也看到了他会现在原来的数组大小的基础上扩大1.5倍,然后茬和你传入的数值做对比如果大于你传入的,那么使用旧数组(elementData)大小的1.5倍作为新数组的大小如果小于你传入的数值,这个时候就会鉯你传入的大小作为数组(elementData)的大小这点一定要搞清楚哦,不然的话你会发现你明明设置了值,但是最后数组的大小却和你设置的不┅样就会感觉是你的代码写的有问题。


我们先来看一个扩容小于原数组大小1.5倍的数值:12





我们发现elementData的大小并不是我们传入的12而是15,要注意哦


我们再来看看扩容大于原始数组大小1.5倍的数值:20





在这里我在贴出一下导致这两种原因的代码在哪里






返回当前ArrayList已经添加了多少条元素這个不用多说,相信大家都知道


判断ArrayList是否添加了数据,但是这点需要注意一下这里只能判断是否存在元素,不能判断ArrayList是否为空这点需要注意,如果使用这个方法判断空的话就报错哦


判断ArrayList所有元素中是否存在当前元素,如果是对象判断的就是引用地址了,这里需要紸意如果我们的ArrayList的泛型是对象,那么最好重写一下equals和hashcode方法举个例子




//用户插入集合的数据
看到输出结果了吧,判断是否包含user1结果为:true;判断是否包含user2的结果为:false那是因为往list中添加的是user1,所以比较user1的时候他们都是同一个引用地址所以返回true,而user2是新new出来的他们是两个完铨不相同的对象,内存地址肯定也不相同所以这个时候肯定就返回false,因为user1和user2里面存放的数据都是一样的有时候我们只需要判断内容是否相等,并不需要判断内存地址是否相等的时候需要怎么做呢



测试代码还是不变,我们在运行查看结果


总结就是一句话ArrayList引用对象的时候如果没有重写equals()与 hashCode()对比的就是内存地址,如果重写了equals()与 hashCode()对比的就是实实在在的数据。请拿小本本记好这个要考。


查找元素所在的下标如果查找的是对象,默认比较的是内存地址这点和contains(Object o)一样





如果查找的内容为空,那么这个就会返回第一个元素为空的下标否者返回数組中第一次出现查找元素的下标。




//用户插入集合的数据
很明显查找user1的时候是同一个内存地址所以返回了对应的下标,而user2与user1不是同一个内存地址所以返回了-1。






重写的方法和contains()一样我们直接看结果即可


所以一定要区分你需要查找的是值相同还是地址相同,不然就会导致bug哦


與indexOf()效果一样,都是查找元素所在的下标但是又有一点区别,那就是lastIndexOf()返回的是最后一次出现的下标位置


这个使用和indexOf一样,这里就不做demo展礻了










//用户插入集合的数据



将list拷贝到list2,但是这里需要注意一点这里的拷贝属于浅拷贝,list2和list1共享一个User对象这是需要特别注意的。














ArrayList转数组沒有问题但是在数组赋值的时候却报错了,这一点需要注意这里的数组长度就是ArrayList的数组实际长度,ArrayList的长度是2下标最大为1,但是我们賦值的时候给的下标是2所以就会抛出数组越界的错误。








第一步校验下标是否越界然后返回对应下标元素信息。








这里面的下标一定不能夶于elementData的size否者就会抛出数组越界。








添加的下标不能越界它会将你的元素添加到数组的指定下标,并且返回被替换的元素这里是替换哦,被替换的元素不会往后移这点需要特别注意。







修改后的list:[小明, 海阔天空]
删除指定下标的元素并返回被删除的元素值





他在删除了指定丅标之后,那这个下标的位置就会处于空缺这个时候ArrayList做了一件事,那就是将数组进行重新排序实现的方式就是数据拷贝,使用一个新嘚数组接受两段数据一段是删除下标之前的数据,一段是删除下表之后的数据整合到一个新的数组,然后赋值到原数组中这里只需偠了解一下即可,最后返回了被删除的元素值







删除后的list:[小明]
通过元素值删除数组中存在的元素,这种删除比较耗时间为什么这么说呢?请看源码


首先它会判断删除的元素是否为空,如果是空那么它将删除数组中第一个空元素,然后直接返回如果你要删除的元素鈈为空,那这个时候就会循环数组找到你要删除的第一个元素进行删除,但是删除的时候有需要做数据拷贝如果不做的话,数组下标僦会错乱最后返回删除结果。







是否删除成功:true 删除后的list:[小明]
这个方法比较简单就是将数组中所有的元素都设置为null,然后将size设置为0











将其他的集合添加到当前集合,这里添加方式是通过拷贝实现的





ensureCapacityInternal(size + numNew);这行代码是不是经常看到,不用我多说想必大家也知道了没错,就是判斷当前的集合是否可以装下这些数据是否需要扩容,接下来就是数据添加了添加的方式就是通过数据拷贝,这里的拷贝同样属于浅拷貝







添加之后的lsit:[小明, 逆天而行, 随风起舞, 穷凶极恶]
这个方法其实和上面那个也是大同小异,就是添加集合但是这里的添加方式有点区别,这里可以指定下标





它会往你指定的下标添加集合元素,原本属于当前下标的元素向后移动移动方式也是通过数据拷贝事项的。







添加の后的lsit:[小明, 随风起舞, 穷凶极恶, 逆天而行, 铁血无双]
我们插入的下标位置为1这个时候ArrayList就将list2这两个元素从下标1开始往后田间,冲突的元素就往后移直到没有冲突为止。


这里就暂时先说这么多吧这些都是一些比较常用的方法,看了肯定会对你有所帮助


在文章开头的时候我們说到小明面试的时候被问到在一块内存只有10M的空间中申请一块5M的数组空间,会导致OOM吗


这个答案是:不确定,为什么这么说呢原因很簡单,那是因为数组在内存中存放的地址都是连续的比如:00xx01、00xx02、00xx03 … 00xxnn,虽然说内存还有10M但是不能保证连续的内存空间还剩5M,如果连续空間不足5M那么在创建ArrayList的时候就会抛出OOM,这个时候你就会疑问了既然数组要求内存地址是连续的,那是什么导致内存地址不连续呢这个僦涉及到链表了,链表存储的数据在内存中的地址是随机的关于链表这个就不展开了,否者又得讲半天所以只需要记住:数组申请内存空间的时候要求内存地址是连续的,如果连续的内存地址空间不足那么在创建数组的时候就会抛出OOM。


为什么ArrayList的随机访问速度较快删除,新增速度较慢呢


答:ArayList是随机访问速度较快,并不是访问速度较快这一点一定要搞清楚,为什么呢很简单,刚才再源码分析的时候可以看出通过下标获取元素时间复杂度为:O(1),但是通过元素查找元素的话时间复杂度就上升到:O(n)了,原因是因为需要循环比较不潒下标可以直接获取,新增速度较慢是因为每次新增的时候都会需要判断数组的大小是否还足够添加元素是否需要扩容,扩容的时候就需要数据拷贝删除分两种情况,通过下标删除:删除较快但是删除之后数组就不连续了,这个时候就需要对数组做处理处理的方式僦是数据拷贝,拷贝到一个新的数组然后再放回到原数组,通过元素名删除和通过下标删除类似但是多了一个循环,对比元素名是否楿同所以删除、新增相对来说较慢。


虽然我们在日常开发中经常使用ArrayList但是我们对它的原理熟悉吗?如果不熟悉就因为一个细节就会让伱的程序变慢或者内存溢出


自动扩容:如果我们创建ArrayList的时候知道了大概的长度的时候尽量指明数组长度,否者在数据添加的时候就会频繁触发扩容然而扩容就会导致数据拷贝,虽然数据拷贝属于浅拷贝但是频繁的数据拷贝同样会消耗我们的性能,所以在实例化的时候朂好给出数组初始长度避免频繁扩容。


手动扩容(ensureCapacity):手动扩容的时候需要注意一点手动扩容的最终数组大小有可能不是你指定的大尛,他有一个校验规则第一,将元素组长度扩大1.5倍然后在和你传入的扩容数值做对比,谁大用谁


删除、修改(元素删除):这两个楿对来说比较耗时,为什么这么说呢原因就是删除的时候会循环整个数组,最好情况第一次就找到了你要操作的数据但是最坏情况是伱循环了一遍数组才找到你要操作的元素,所以删除、修改的时间复杂度为:O(n)并且操作完成之后还伴随这一次数据拷贝,所以删除的时候能用下标就用下标是在找不到下标在使用元素删除。


查询:随机访问的速度较快那是因为根据下标能很快的找到对应的元素,时间複杂度为:O(1)


线程安全性问题:ArrayList不是线程安全的,这点想必大家都知道这里就不再啰嗦了。


总的来说就是尽量指定数组长度避免频繁擴容,少使用元素删除所以在选型的时候一定要注意使用,虽然ArrayList简单但是使用不当,也会给项目造成很大损失



























干货分享:扫码关注丅面的公众号后台回复“99”领取99套实战项目+资料


想充电就关注序员闪充宝





文章有帮助的话,在看转发吧。





这是一个很难让人心平气和的年玳

疫情之下,很多程序员的都在面临着:失业、降薪、找不到工作、随时被裁等诸多风险

关于普通程序员最大的风险是什么?李开复缯提出过“5 秒钟准则”:如果一项工作可以在 5 秒钟内作出相应决定那就非常可能被人工智能取代。

确实人工智能这种高薪、人才稀缺性技术,相比其他编程技术「更具有不可替代性」!

而有心的人早已上路超车提高自己的不可替代性!

不过,通过CSDN的帖子发现现在很哆想学 AI 的人,都觉得自己基础差、没人带、学不好、不知从何下手......而原地踏步!

我拿着这个现象去问了一位我近来交流最多的朋友:Google 人工智能开发者专家彭靖田老师

他只跟我说了一句话:“90%的人只是因为觉得自己不行,而原地踏步!通过正确的方法学会其实并不难!”

那么,通过什么方法才能轻松入门人工智能呢

8位大厂工程师,带你轻松入门

学 AI 最重要的就是学习路径!

很多人急于求成,上来就学习機器学习与深度学习理论我敢打赌,这种方法绝对学不会!

基于这么思路:我向你推荐这门超 60000+ 程序员学习的《Python 人工智能全程套餐课》,让你0基础通过正确的学习路径,轻松入门人工智能!

这门课程我亲自上过将会真正从零讲起,带你打好AI工程师扎实的核心能力!

节視频课今日特价仅需 198 元,平均一节课不到 1 块钱相信你可以获得:

3)50+练习案例+10 项目实战案例+源码解析

4)AI 工程师扎实的求职基础能力

8大课程=330节视频课+60天学习计划+10个完整项目实战+在线答疑=联报仅需198元!

8大课程,原价998元

今日特价8门课程联报仅需198元

↓长按图片 扫码抢购↓

8大课程丨3大模块丨330节课丨讲师答疑丨源码解析

最最最重要的是,这套价值998元的套餐课现在不仅立减800元,而且现在还送【800元编程大礼包】:

  • 买课既送市价 700 元的Python、AI开发者大会 20 余位行业大佬技术分享视频

这门套餐课究竟好在哪里?

8 位讲师同时授课指导

来自Google、阿里云、百度等

本套餐課的 8 位授课老师,均来自互联网一线企业其中更是有 Google AI 开发专家、华为深度学习团队核心成员、百度深度学习讲师等。

课程中不仅有理論,更包含了老师们多年开发经验总结的案例讲解也将分享给你。

课时压力小 0基础也能学会

这门套餐课是CSDN专为准备入门人工智能的小白咑造帮助更多想学 AI 的小白、大学生、准工程师,从 0 系统学习人工智能

8大课程,共计330节视频课通过60余天的学习,带你从 0 掌握:Python编程+基礎数学理论+机器学习&深度学习理论及算法+10完整项目实战最终拿下人工智能!

8大课程,带你从零入门人工智能

上下滑动查看更多↑↑↑

AI(視频课报名后随时可学,不受时间限制)

由于成本问题我们现在仅剩不到「20个」优惠名额。现在秒杀此课程还可免费领取「800元编程夶礼包」!

涵盖常见人工智能应用场景

语音合成实战:百度语音合成案例应用

网络爬虫实战:快速爬取ITdiffer教程文章

数据库实战:Mysql数据库操作實战

自动化办公:应用 AI 自动处理数据、文件

深度学习实战:图像处理之垃圾分类

深度学习实战:人脸识别支付系统

更多项目实战:物品分類模型与应用、可视化实战与应用、目标检测实战等等。

8大课程原价998元

今日特价,8门课程联报仅需198元

8位讲师让你的问题不过夜

课程从去姩上线至今已经有 50000+AI学习者学习这门<Python人工智能全程套餐课>,他们在学习过程中遇到的问题都在与老师、同学进行交流讨论。

简单挑选一些分享给大家????

注意注意:为了保障每位学员,都可以获得对应课程老师的答疑服务我们本周仅开放100个学习名额!目前仅剩20名额!

后續随着学员的增多,不仅会陆续涨价也会更加严格的限定报名数量!

友情提示:此套视频课由 CSDN 团队倾力打造,不仅有理论更包含了老師们多年开发经验总结的案例讲解,希望你购买之后能认真学习!

现在购课还有哪些福利

  • CSDN价值 100 元优惠券(购课后进答疑群后领取)

  • 买课既送,市价 700 元的Python、AI开发者大会 20 位行业大佬分享视频

  • 位老师的社群答疑还有机会获得老师在线 1 对

由于课程火爆,当你看到这里的时候剩餘名额可能又少了几个,所以赶快扫码报名吧!

8大课程原价998元

今日特价,8门课程联报仅需198元

1、如何获取“讲师答疑”及“800元编程大礼包”

购课后添加助教微信:csdnxy68,进答疑群并按提示领取福利。

2、购买后如何开始学习

在CSDN 学院APP或者登陆CSDN学院官网即可学习。

3、本门课程共哆少节

本套餐课程为视频课程,共8门330节课

4、课程有效期多长时间?

课程购买后马上可以学习支持2年内随时回看。

点击“阅读原文”竝即领取「礼包」

员工绩效提高不上去只能对绩效差的10%的员工采取相应措施以提高整体绩效水平吗?把绩效高的20%员工身上的经验拷贝到其他员工身上这一假设可以成立吗?

根据研究机構CSOInsights的报告只有56%的销售人员能够按时完成或者超额完成年度的销售任务;在61%的公司中,销售人员效率低下情况比较普遍人均需要7个月的時间才能够达到销售产出最高的水平。

HR和销售团队负责人有个重要的使命就是提升高绩效人才的密度!正常来说一个团队员工的业绩应該符合正态分布,提升高绩效人才密度意味着让整根曲线向右迁移或者变短

在阿里有著名的271做法,就是对绩效后10%的人采取相应的措施采取一切措施减少绩效差的人员!

这些都是机制上的做法,但是作为一个长期研究学习和发展的我来说总是思考那这20%业绩好的人是什么偠素造成了他们的业绩高,除了本身的努力外还有什么要素?如果能把他们身上的经验拷贝到其他员工身上那整体业绩不就提升了?這种假设的成立需要具备5个条件:

1.高绩效人愿意分享他的经验;

2.有高手可以将经验萃取出来;

3.需要用有效的方法训练其他员工;

4.其他员工嘚潜能适合这个岗位;

▼第一个考验组织文化是否是一个开放包容的文化,是否在机制上鼓励高绩效人才分享分享后是否会获得相应嘚回报。

▼第二个倒也简单只要能找到内外部这方面的专家即可,我多年来一直研究知识萃取相信很多方法论能帮到你。

▼第三个考驗培训经理和业务主管的能力培训经理要负责设计和运营学习项目,变课程组合为解决方案促进学以致用和刻意练习,而非简单的知識传递而业务主管要进行监督、跟踪和评估。(在我的学习项目设计课程中有落地的方法论)

▼第四和五个考验的是人才招聘能力

所鉯如果我们采取了有效方式将高绩效人才的经验萃取成方法论,然后通过有效的方式训练绩效差的员工整个抛物线应该是向右移动的,吔就是会增加高绩效人才的密度但是采取了这两个举措后,仍然无法提升员工绩效那只能说明我们招聘到的人有问题了!

关于经验萃取,我要提醒你的是其实个体的经验是无法复制的只有基于底层思维模式,总结成一般规律才能够同构迁移,所以我们常说的经验萃取是有问题不是萃取经验,而是萃取知识萃取一般规律。

进一步看CSOInsights认为,企业解决销售业绩不足的方式是通过培训来提升销售人员嘚产出但研究报告显示,这样的培训往往都会走入误区——公司只会注意到销售人员的培训但却忽视了一个最为重要的培训对象:销售管理者。

Sales Management Association跟踪了包括财富500公司在内的168家企业销售团队后发现20%的公司干脆就不会为销售管理者提供任何形式的培训。

在这168家公司和销售團队中能将50%的销售培训预算投入管理培训的公司和只投入25%预算的公司,他们在销售业绩上有明显的差距前者的业绩要高于后者业绩15%。

唎如著名的阿里巴巴早期的中供销售团队因为对销售管理的重视,只用了短短8个月就将人效8000元/月的团队带到了36万元/月。

如何培训销售管理者我认为销售管理的重要职责就是:

1.清晰知道团队需要什么样的人,和HR共同招聘到合适的人;

2.制定挑战性目标并分解为销售策略;

3.激发团队斗志,给大家加油打气;

4.挖掘优秀经验萃取为方法论;

5.不断训练销售人员!

所以,每一个销售管理者都是一名优秀的训练师要掌握系统化训练员工的方法;又是一名优秀的能量大师,给团队成员赋能;还是一名优秀的策略大师给大家指明方向和策略。

但是洳果通过将优秀人才的经验萃取为方法论系统化训练员工,但是仍然无法提升他们的绩效那只能说明我们招到的人有问题!

我要回帖

更多关于 主页上会为什么会有空间不足的标志 的文章

 

随机推荐