集合框架1,数组集合ArrayList

来源:互联网 发布:淘宝店铺名推荐 编辑:程序博客网 时间:2024/05/17 22:13

数组是有限存储,集合做到无限存储。ArrayList数组集合,是怎么做到无限存储的?原理很简单。


数组长度是定死的,一旦申请不能对原数组的长度进行扩张,这称为有限,但数组长度有限,但可有对创建多少个数组对象有限制?


数组存多个值这是方便的,数组长度不可变是数组的缺点,为了更加灵活,没有限制的存储值,应运而生,出现了“集合”。


集合有数组集合,双链集合,hash集合,二叉树集合,本文谈ArryList数组集合。


数组集合的无限添加已经写在了add方法中,先分析一下,ArrayList数组集合,之前提到了,数组是有限存储,但可以new多个数组对象来做无限存储。


用数组做无限存储,思路如下:申请一个全局变量Object数组(包容所有),开始存储值的时候,先询问数组是否为null?是否没有引用数组对象,


如果是:新建一个长度为5的数组,else if()进不去,先不探讨这里,跳过else if(),开始存储第index++个值,也就是数组有了5个长度,第0个下标第一个长度存储了第一个值。


第二次存储,数组已经有了引用对象,不在为null,依然跳过else if(),开始存储index++个值,刚才的index++=0,index=0;index++变成了1,所以第二次存储值拿到的是后加完了的1的值,也就是下标为1长度为2这个地址存储了第二个值。


第三次index++变成了2,下标为2长度为3存储了第三个值,第四次index++变成了3,下标为3长度为4存储了第四个值,第五次index++变成了4,下标为4长度为5存储了第五个值,


现在在第一次还等于null时,申请5个长度的数组已经不够用了。已经存不下第六个值了,在存储就该越界了,此时就应了之前的一句话,数组长度是有限的,但数组可以new多个对象。


刚刚第五个的index++,下标是4,长度是5存储了第五个值。在第六个时候,该进入else if()了,在else if()中问啊,这个数组的实际长度,leng==index,


5==index?肯定不等于啊,刚刚还说第五次存储下标是4长度是5,没错下标是4确实是存储到了数组的最后一个实际长度5上面,但是index++,


在第五次存储的时候是得到的第四次index++后加的int值,也就是4,所以在第五次的存储的时候,长度是4存储的是最后一个,不过存储完了最后一个后,index++,默默的后加为了5。


所以数组实际长度,等于index++,已经知道了,数组的长度和index++长度相等了。index++第五次后加,后index等于5,数组实际长度等于5,说明第六次存储,你数组要有第5个下标,我才能给你存储到第六个实际长度上。否则越界。


因为我这第六次的下标5已经加好了,给你拿过来作为存储我第六个值的下标,如果你没有,说明你该再次新建一个更大的数组对象进行值存储了。


所以else if(index==数组长度)是判断,你数组长度还够不够?够你当然可以按着我index存,若是等于我index,实际长度和我下标长度相等,肯定会存不下报错的,即可进入else if


在else if中,新建一个数组对象,长度是老数组的2倍。老数组在引用新数组地址,周而复始,满了继续新建对象引用,做到了无限存储。


在这个集合添加方法中,我们并没有对数组的长度进行扩展,也做不到,而是灵活运用了数组对象做到无限存储,可见思想的重要性。


集合不能只有添加,还应该有返回长度的方法,删除方法。


返回长度方法,直接返回index长度即可,最合适不过了, 当使用集合的人像集合添加了5个值,index是从0开始的,在添加完第5个值时,index++,index等于4,index++后加等于5,在数组第四个空间就存好了传入的第五个值,返回index++后加的5,就不会给人误会。


删除方法,ArrayList数组集合是拿数组做的,数组不能做到改变自身,或许你会想为null吧,但到了应用的时候为null是不合适的,后面讲解。



我的删除方法,用System.arraycope拷贝自身,是这样设计的,你需要删除第几个,你传入下标,我拿着你这个下标+1(计算的结果是下标的后一个),拿着后一个,拷贝到你传入下标的这个位置。即可。


首先这样做是可行的,有几个注意的地方,

1:如果你传入的下标是删除的是最后一个,怎么获取最后一个在后一个拷贝到这个下标呢?


2:拷贝,把下标后面值的全部拷贝到下标处,这是拷贝可不是剪切,下标后面的全部复制到下标后,由于是拷贝最后是吊一个重复的值,调用删除方法拷贝的越多,重复的最后一个值越多。


3:如果你调用删除方法,已经删掉了一个,index也--了,然后没事又去删最后一个,虽然有值,可删,但是逻辑上说这个地方已经没有值了,怎么办?这里表达比较晦涩,后面讲解。


4:如果你添加值,然后你一个劲调用删除方法。删的比存的还多,难道不考虑缩容,还有必要给你这么长的长度吗?恐怕有点不合适了。


第一个问题解决:

删前面的好删,删最后一个也很简单,null都不用置,直接index--即可,为什么呢?当你删除最后一个,index--,再次添加的值的时候,获取到的是index下标进行添加,


添加完最后一值,第6次调用add(),得到的上一次第五次后加的index为5,存储的下标为5长度在第六个上的值,第六个存储完毕后,index++后加,等于6,也就是不出意外,下一次添加也就是该是存储在下标为6的第一个长度上。


此时偏要,删除第六个,index--,再次调用添加的方法时候,获取的是index==5;这次添加也是就是存放在下标为5,长度为6这个地址上。直接一覆盖,在下一次,不出意外才是存储在下标为6长度为7的长度上。


第三个问题解决:删除了一个,拷贝后会重复一个尾数,不用管,当你要删这些重复尾数时,这就不妥了,比如数组长度为10,存了6个值,你删除2个,index从下标6变成下标4。


删除2个,逻辑上来说数组10个长度,会从存的5个变成存的3个,下标会从6变成4,但由于拷贝删除方法,删2个重复2个,你想删这2个重复,虽然这里有值,但从逻辑上来说这里已经没有值的,所以不能给删,可以选择报错。


我采用的是if(i<index),接着上面题,你删了两个后,按照逻辑,数组长度10中存的5个变成3个。index从6变成4,传入下标5,5<index?5<4当然不,就不指定if里面的代码,算作不给删。


if可以抛一个异常,我就懒得做了,如果传入的下标回到上例,第一次删除,传入4,数组长度10存的5个值,index后加后为6,if询问,4<index;4<6,小于所以删,用传入的下标和index的下标做比较即可得出可否给你删。


最后一个问题解决:

删的多了,空余的比我存的还多,明显长度就不合适了,可以考虑缩容了。怎么用代码判断是否你空余比我存的还多?我的做法是:用数组长度减去index,是否大于index,即可判断是否到达了一半。


首先,先明确一点,index是干嘛的?index是下标,通过它能确切的知道在一个数组的实际长度中,存了多少个值?比如,数组实际长度是10,调用5次添加方法,此刻,在数组中是从0~4存了5个值,index是4,index++后加后等于5.


index++后加后得到的是5,数组存的5个是0~4存了5个,数组实际长度减去index,能得到,你数组还有多少个没有存?5,6,7,8,9还有这5个值没存,为什么没有10?因为当你用下标9存完第10个值的时候,index++后加为10,不扩容,就没有10了。


删了一个后,index=4,数组长度-index=6,index<数组长度-index,也就是左边的存的小于了右边空的,就该缩容了。如果是大于右边空的或是等于我都不动你,但当你小于时,就缩容把。


缩容的方法:在新建一个对象,长度我申请的是index+1;此时index==4,在添加值的话,就添加到index为4的下标上,也就把数组最后一个空余的补上,如果申请长度为index个,数组长度的关于index新建一个数组罢了,一样。


关于这个ArrayList,集合嘛就是做到无限存储,ArrayList是用新建数组导入值存储值做出来的。数组涉及到下标实际长度,我感觉挺绕的,可能是我练习还不到位吧。


最后再来推算一波:调用6次add()方法,前5次,index分别是0,1,2,3,4在第一次为null时创建的长度为5的数组被存满。存完第5个,index++后加为5,第六次存储,index==数组长度?数组还没有扩容,5==5,成立,


新建长度为10的数组,拿到index存储在数组下标第5个中,实际长度为6的上,此刻返回长度,返回后加的index,6==6次调用,成立。调用4次删除方法。


数组中下标7变成3,逻辑上实际长度6变成2,index<数组长度-index?3<7缩容,在减去第3次的时候即开始缩容。完毕。


ArrayList数组集合,添加速度快,定一个长度就可以进行存值,满了新建一个数组又继续存,这种结构在添加速度上优势明显,


同时,是一个有序集合,添加的值一个个都按照下标一个个往后添加,而不是无序的添加,


还可以添加重复值,有的集合不能添加重复值,后面会讲解,


数组集合ArrayList,是一个用数组做出来的集合,对存储数据这一块速度非常快,存满了在申请新数组存储,这样按照下标存储值是很快的,为什没说ArrayList查找速度慢呢?明明从前之后查找速度应该也不会差到哪里去。


那是因为对比hash集合就慢多了,对比下来,完全没有优势,被甩几条街,所以合理使用集合,效率会提升不少。


他的index这个全局变量解决了很多问题,返回值,判断是否删除一半,以及存储都是,都是和index挂上练习的,没有index也能做到存储,删除,修改值,但是会比较麻烦。