首先,先看一下java中对ArrayList的定义代码:

public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
private static final long serialVersionUID = 8683452581122892189L; /**
* Default initial capacity.
*/
private static final int DEFAULT_CAPACITY = 10; /**
* Shared empty array instance used for empty instances.
*/
private static final Object[] EMPTY_ELEMENTDATA = {}; /**
* The array buffer into which the elements of the ArrayList are stored.
* The capacity of the ArrayList is the length of this array buffer. Any
* empty ArrayList with elementData == EMPTY_ELEMENTDATA will be expanded to
* DEFAULT_CAPACITY when the first element is added.
*/
private transient Object[] elementData;

  这段代码能给我们提供的信息:
     第一:ArrayList实现了RandomAccess接口,因此查询会很快

第二:ArrayList实现了序列化和Cloneable接口,讲道理应该可以进行克隆操作,但是这里有争议说不是,因为这样操作是同一个对象,不过我自己测试不是一个对象。存在争议点。。。

第三:ArrayList底层使用数组实现,这个数组默认的长度是10.

好了,从上面的代码似乎只能得到这些结论。但是既然是ArrayList,一定是长度可以增加的,这样推理的话,数组肯定是可变的,倘若再沿着Arraylist的定义文件代码往下看,确实是这么回事。但既然是浅度解析,就不一一分析全部代码了,结论就是ArrayList底层用一个可变数组进行对元素的存放,这个数组初始长度是10,而且根据情况可以进行扩容。

对于扩容,我们会关心的一个问题是:每次扩多大啊?倘若一次扩容太大,就会造成空间浪费啊,如果扩的不够,就会频繁出现扩容操作,也是会消耗性能。对于这个问题,设计者为我们选取一个折中的大小,倘若原来大小的size表示,扩容后的大小为:size*3/2+1。

然后说说ArrayList扩容用的底层,就是数组的拷贝:Arrays.copyOf(array0,newSize);基于数组的拷贝,ArrayList的删除元素的操作流程可以分为以下三个步骤:

①删除数组指定位置的元素。②将后面所有元素进行数组拷贝操作向前移动一个位置。③最后一个元素置为null,让垃圾回收机制进行回收空间。

数组添加元素跟删除道理差不多。基于这个情况,我们可以得出ArrayList的两个缺点:

1、删除元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能

 2、插入元素的时候,涉及到一次元素复制,如果要复制的元素很多,那么就会比较耗费性能
   既然ArrayList能成为被用的这么广泛的集合,不可能只是因为这俩缺点,优点也写对应吧:

1、ArrayList底层以数组实现,是一种随机访问模式,再加上它实现了RandomAccess接口,因此查找也就是get的时候非常快

2、ArrayList在顺序添加一个元素的时候非常方便,只是往数组里面添加了一个元素而已

所以说ArrayList适合顺序添加,随机访问,而像LinkedList则适合插入删除等较多的集合操作。只能说大多情况,针对特定的效率也不尽然,因为是数组拷贝操作,ArrayList对于较靠后的元素的删除和添加操作速度反而会比LinkedList快很多呢。

最后写点备忘的技巧:

①ArrayList是线程不安全的,如果非需要线程安全的话,可以使用Collections.synchronizedList来,操作如下:

List<String> list= Collections.synchronizedList(list);
list.add("aaa");
list.add("bbb");
for (int i = 0; i < list.size(); i++)
{
System.out.println(list.get(i));
}

 ②对于集合操作,如果实现了RandomAccess接口(如ArrayList),尽量使用for(int i=0;i<size();i++)这种方式进行遍历,比增强的for循环效率快一倍。而没实现RandomAccess的(如linkedList),如果使用普通的for循环比使用迭代器效率低上千倍。所以:

   if (list instance of RandomAccess) {
for(int m = 0; m < list.size(); m++){}
}else{
Iterator iter = list.iterator();
while(iter.hasNext()){}
}

  

常用集合ArrayList浅度解析的更多相关文章

  1. JAVA常用集合源码解析系列-ArrayList源码解析(基于JDK8)

    文章系作者原创,如有转载请注明出处,如有雷同,那就雷同吧~(who care!) 一.写在前面 这是源码分析计划的第一篇,博主准备把一些常用的集合源码过一遍,比如:ArrayList.HashMap及 ...

  2. java常用集合浅层解析-面试必备

    ArrayList 1.动态数组 2.线程不安全 3.存储空间连续 4.查询快,添加删除慢 构造方法 /** + Shared empty array instance used for defaul ...

  3. Java List 常用集合 ArrayList、LinkedList、Vector

    Java 中的 List 是非常常用的数据类型.List 是有序的 Collection,Java List 一共有三个实现类,分别是:ArrayList.Vector.LinkedList 本文分析 ...

  4. Java常用集合笔记

    最近事情比较少,闲暇之余温习巩固一下Java的一些基础知识,并做一些笔记, Java常用集合, 主要参考的这篇文章:Java常用集合 ArrayList/Vertor 1. ArrayList 的主要 ...

  5. C#-正则,常用几种数据解析-端午快乐

    在等待几个小时就是端午节了,这里预祝各位节日快乐. 这里分享的是几个在C#中常用的正则解析数据写法,其实就是Regex类,至于正则的匹配格式,请仔细阅读正则的api文档,此处不具体说明,谢谢. 开始吧 ...

  6. Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 [ 转载 ]

    Java 集合 ArrayList和LinkedList的几种循环遍历方式及性能对比分析 @author Trinea 原文链接:http://www.trinea.cn/android/arrayl ...

  7. 比较Java中几个常用集合添加元素的效率

    初始化需要进行比较的集合,统一增加10万个元素,获取整个过程的执行时间. 1.List集合增加元素 private static void testList() { List<Integer&g ...

  8. 【转帖】Linux上,最常用的一批命令解析(10年精选)

    Linux上,最常用的一批命令解析(10年精选) https://juejin.im/post/5d134fbfe51d4510727c80d1 写的挺好呢 Linux这么多命令,通常会让初学者望而生 ...

  9. C#常用集合

    数组的缺点:长度固定.因此引入集合的使用. 注:泛型集合更安全,性能更高. 常用集合 对应泛型 ①动态数组ArrayList    List<T> 常用方法属性:Add  Clear  C ...

随机推荐

  1. HAProxy的访问控制

    HAProxy的ACL用于实现基于请求报文首部.响应报文的内容或其他的环境状态信息来做出转发决策,这大大增强了其配置弹性,其配置法则通常分为两步,首先去定义ACL,即定义一个测试条件,而后在条件得到满 ...

  2. AFNetworking 和 ASIHTTPRequest

    在开发iOS应用过程中,如何高效的与服务端API进行数据交换,是一个常见问题.一般开发者都会选择一个第三方的网络组件作为服务,以提高开发效率和稳定性.这些组件把复杂的网络底层操作封装成友好的类和方法, ...

  3. Python之------初识面向对象(Day22)

    一.面向过程 VS 面向对象 面向过程的程序设计的核心是过程(流水线式思维),过程即解决问题的步骤,面向过程的设计就好比精心设计好一条流水线,考虑周全什么时候处理什么东西. 优点是:极大的降低了写程序 ...

  4. spring 异步处理request

    转自:http://blog.csdn.net/u012410733/article/details/52124333Spring MVC 3.2开始引入Servlet 3中的基于异步的处理reque ...

  5. pyhton3 configparser模块

    1 #!/usr/bin/env python 2 # coding=utf-8 3 __author__ = 'Luzhuo' 4 __date__ = '2017/5/26' 5 # config ...

  6. 026_默认的MapReduce Driver(最小驱动问题)

    1. 最小配置的MapReduce Driver 读取输入文件中的内容,输出到指定目录的输出文件中,此时文件中的内容为: Key---输入文件每行内容的起始位置. Value---输入文件每行的原始内 ...

  7. Shell编程之for和select循环

    一.for和select循环 1.for循环语法 for 变量名 in 变量取值列表 do 指令... done C语言型for循环 for ((exp1; exp2; exp3)) do 指令... ...

  8. scope 作用域

    每当一个指令被创建的时候,都会面临一个选择:继承父作用域,还是创建一个自己的作用域.Angular为指令的scope参数提供了三种选择,分别是: false(继承), true(不继承), {},默认 ...

  9. INSPIRED启示录 读书笔记 - 第6章 招聘产品经理

    产品经理应有的特质 个人素质和态度:技术可以学习,素质却难以培养,有些素质是成功的产品经理必不可少的 对产品的热情:对产品有一种本能的热爱,是夜以继日克服困难.完善产品的动力 用户立场:能换位思考,能 ...

  10. 算法总结之 在单链表和双链表中删除倒数第k个节点

    分别实现两个函数,一个可以删除单链表中倒数第k个节点,另一个可以删除双链表中倒数第k个节点 思路: 如果链表为空,或者k<1 参数无效 除此之外 让链表从头开始走到尾,每移动一步,就让k的值减1 ...