ArrayList:或许有你不知道的
2014-02-10 20:19
162 查看
ArrayList 底层以一个transient 线性数组来存储数据,它提供了无参构造方法,和有参构造方法,用户可以通过有参构造方法来初始化长度。如果不传参数,则默认调用无参构造器,数组默认长度为10。
关于数组长度的问题,ArrayList专门提供了一个方法来管理,以避免数组越界。如下:
![](http://images.cnitblog.com/blog/600147/201402/101751146455981.jpg)
方法参数为将要达到的长度(newLen),将它与数组实际使用的长度进行比较(factLen),如果newLen>factLen那么将要拓展数组长度。拓展的量为(factLen*3)/2+1(实际上这种情况下,数组的使用长度和开辟长度是相等的),为什么是这种算法?实际上它是在原来的基础上增加50%+1,之所以要加1是因为,执行这个方法的时候通常是需要往数组里面添加数据,数组需要为当前数据保留一个位置,从而保证数组预留位置为原来的1.5倍.
这个方法在何时执行呢,搜索发现,在四个方法执行,分别是add(E),add(index,E),addAll(c),add(index,c),也就只要需要往数组里面添加数据,都需要对数组索引及长度进行判断,以避免数组越界。
而且可以发现,当数组长度重新拓展以后,会把当前数组的数组复制到新长度的数组。这将是非常影响效率的操作。
ArrayList的get()和add()方法都比较简单,首先都需要进行数组越界的考量判断,然后通过索引得到相应的值,值得注意的一点是,add(index ,e)这个方法,做了两个判断,索引小于0和大于当前实际使用值,都是不合法的。比如,初始化后数组长度为10,里面存了5条数据,当前最大使用的索引为4,此时调用add(5,obj),这是会抛出数组越界。这是为ArrarList为了保证分配连续的内存空间。
![](http://images.cnitblog.com/blog/600147/201402/101751327368108.jpg)
ArrayList的remove方法,如果传的是一个索引值,首先判断索引是否越界,然后执行删除,并返回删除值。如果传的是一个对象,那么首先会判断对象是否为空,如果为空,遍历数组,找到则执行类似于remove(index)的方法,区别在于没有返回值,如此可见,ArrayList是允许空值的;如果不为空,同上。
![](http://images.cnitblog.com/blog/600147/201402/101751491217448.jpg)
既然它可以为空,那么可不可以覆盖掉它,根据前面所说,索引小于0和大于当前实际使用值,都是不合法的,会不会抛异常呢?测试了下,发现不会,新的值占用了原先的位置,但数组实际所使用的长度不变,证明与其说是覆盖,不如说是把原值挤走了。为NULL的值优先级不高。而且,在GC工作的时候可能被回收。如图:
![](http://images.cnitblog.com/blog/600147/201402/101753357532057.jpg)
需要注意的是,ArrayList在删除某条数据所做的处理,仅仅只是将该处索引的值设为NULL。这时整个数组的实际使用长度是没有做出改变的,如果刚好逼进临界点,在下次增加时会拓展长度。
![](http://images.cnitblog.com/blog/600147/201402/101753033024475.jpg)
只有在clear()方法的时候,才会对此做出处理。
![](http://images.cnitblog.com/blog/600147/201402/101754220337762.jpg)
说说两个重要的属性,transient ,modCount,ArrayLIst里保存数据的数组修饰符为transient,表示它不作为序列化的一部分,在进行读写操作的时候需要调用方法。readObject,writeObject,而modCount负责记录ArrayList里操作或者叫做数组改变的次数,在进行读写操作的时候,用modCount进行标记,如果值改变,表明此时另外的线程在对集合进行修改,此时抛出异常ConcurrentModificationException()。
结属说说用得较少的两个方法:
有一个set(index,e)方法,它会用新值覆盖旧值,并返回被覆盖掉的值。
![](http://images.cnitblog.com/blog/600147/201402/101755318164515.jpg)
还有一个listIndexOf()方法,这个方法返回相应对象在数组里面的索引,没有返回-1。遍历,从最后一位开始。
![](http://images.cnitblog.com/blog/600147/201402/101754564598445.jpg)
关于数组长度的问题,ArrayList专门提供了一个方法来管理,以避免数组越界。如下:
![](http://images.cnitblog.com/blog/600147/201402/101751146455981.jpg)
方法参数为将要达到的长度(newLen),将它与数组实际使用的长度进行比较(factLen),如果newLen>factLen那么将要拓展数组长度。拓展的量为(factLen*3)/2+1(实际上这种情况下,数组的使用长度和开辟长度是相等的),为什么是这种算法?实际上它是在原来的基础上增加50%+1,之所以要加1是因为,执行这个方法的时候通常是需要往数组里面添加数据,数组需要为当前数据保留一个位置,从而保证数组预留位置为原来的1.5倍.
这个方法在何时执行呢,搜索发现,在四个方法执行,分别是add(E),add(index,E),addAll(c),add(index,c),也就只要需要往数组里面添加数据,都需要对数组索引及长度进行判断,以避免数组越界。
而且可以发现,当数组长度重新拓展以后,会把当前数组的数组复制到新长度的数组。这将是非常影响效率的操作。
ArrayList的get()和add()方法都比较简单,首先都需要进行数组越界的考量判断,然后通过索引得到相应的值,值得注意的一点是,add(index ,e)这个方法,做了两个判断,索引小于0和大于当前实际使用值,都是不合法的。比如,初始化后数组长度为10,里面存了5条数据,当前最大使用的索引为4,此时调用add(5,obj),这是会抛出数组越界。这是为ArrarList为了保证分配连续的内存空间。
![](http://images.cnitblog.com/blog/600147/201402/101751327368108.jpg)
ArrayList的remove方法,如果传的是一个索引值,首先判断索引是否越界,然后执行删除,并返回删除值。如果传的是一个对象,那么首先会判断对象是否为空,如果为空,遍历数组,找到则执行类似于remove(index)的方法,区别在于没有返回值,如此可见,ArrayList是允许空值的;如果不为空,同上。
![](http://images.cnitblog.com/blog/600147/201402/101751491217448.jpg)
既然它可以为空,那么可不可以覆盖掉它,根据前面所说,索引小于0和大于当前实际使用值,都是不合法的,会不会抛异常呢?测试了下,发现不会,新的值占用了原先的位置,但数组实际所使用的长度不变,证明与其说是覆盖,不如说是把原值挤走了。为NULL的值优先级不高。而且,在GC工作的时候可能被回收。如图:
![](http://images.cnitblog.com/blog/600147/201402/101753357532057.jpg)
需要注意的是,ArrayList在删除某条数据所做的处理,仅仅只是将该处索引的值设为NULL。这时整个数组的实际使用长度是没有做出改变的,如果刚好逼进临界点,在下次增加时会拓展长度。
![](http://images.cnitblog.com/blog/600147/201402/101753033024475.jpg)
只有在clear()方法的时候,才会对此做出处理。
![](http://images.cnitblog.com/blog/600147/201402/101754220337762.jpg)
说说两个重要的属性,transient ,modCount,ArrayLIst里保存数据的数组修饰符为transient,表示它不作为序列化的一部分,在进行读写操作的时候需要调用方法。readObject,writeObject,而modCount负责记录ArrayList里操作或者叫做数组改变的次数,在进行读写操作的时候,用modCount进行标记,如果值改变,表明此时另外的线程在对集合进行修改,此时抛出异常ConcurrentModificationException()。
结属说说用得较少的两个方法:
有一个set(index,e)方法,它会用新值覆盖旧值,并返回被覆盖掉的值。
![](http://images.cnitblog.com/blog/600147/201402/101755318164515.jpg)
还有一个listIndexOf()方法,这个方法返回相应对象在数组里面的索引,没有返回-1。遍历,从最后一位开始。
![](http://images.cnitblog.com/blog/600147/201402/101754564598445.jpg)
![](http://www.the-numbers.com/video/This-Is-The-End/This-Is-The-End-poster.jpg)
相关文章推荐
- 或许你不知道:ArrayList
- 或许您还不知道的八款Android开源游戏引擎
- HDU 5353 Average(这里或许有你一直WA的原因)
- 将思绪从电脑前拉回我的。淘宝小店。或许有你所需!
- 你或许不知道的javascript细节
- 或许你不知道的10条SQL技巧
- OGNL,可能你会用,但这里也许有你不知道的东西···(转)
- JavaScript中的数据类型知识总结(一定有你不知道的秘密~)
- 你不知道的Java小知识——动态数组实现(ArrayList原理)
- 或许您还不知道的八款Android开源游戏引擎(转)
- AspNet中你或许不知道的技巧(转)
- 或许你不知道的10条SQL技巧
- SQL优化之道 - 或许你不知道的10条SQL技巧
- 或许你不知道的10条SQL技巧((sql 优化 sql索引优化))
- Content-Script-Type的设置好象没多大用处,或许我不知道有什么用
- 或许你不知道的10条SQL技巧
- 或许您还不知道的八款Android开源游戏引擎
- 自己写的一个ArrayLIST,but 不知道怎么很好的实现System底下的arraycopy方法
- 或许你不知道(2):LinkedList
- 或许您还不知道的八款Android开源游戏引擎