相信对于使用过Java的人来说,ArrayList这个类大家一定不会陌生。

数据结构课上讲过,

Array是数组,它能根据下标直接找到相应的地址,所以索引速度很快,但是唯一的缺点是不能动态改变数组的长度,复杂度O(1)。

而List就是链表,它搜索相应地址都只能从链表头部一个一个找下去,直至找到对应的地址才停止,相比于数组来说,搜索速度肯定是慢的,但是有点是能动态的增删节点,复杂度O(n)。

而Java中这个ArrayList到底是什么东西呢?

先上代码,我们平时使用ArrayList一般这样使用:

public class ArrayListTest {

    public static void main( String[] args ) {
List<Integer> list = new ArrayList<Integer>();
list.add( );
list.add( );
list.get( );
list.remove( );
}
}

好,现在来解释每一步操作jdk做的事:

先看new ArrayList<>()初始化,

    public ArrayList(int initialCapacity) {
super();
if (initialCapacity < )
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
} /**
* Constructs an empty list with an initial capacity of ten.
*/
public ArrayList() {
this();
}

很明显,如果初始化不指定capacity的话,默认初始化数组大小就是10。

其实细心发现,在重载的构造函数中,

this.elementData = new Object[initialCapacity];

这行代码暴露了ArrayList的本质,其实就是一个数组。

OK,现在我们拥有了一个长度为10的数组对象,现在我们执行add操作,看jdk操作

    public boolean add(E e) {
ensureCapacityInternal(size + ); // Increments modCount!!
elementData[size++] = e;
return true;
}

1.首先,暂且不理会ensureCapacityInternal()方法做的事,直接看【elementData[size++]=e】这行代码,显然地,是在elementData对象的size索引位置指向新元素,问题来了,万一size已经超出了当前数组的最大长度(假设是在第11个位置放置新元素),怎么办?

这里就要看ensureCapacityInternal方法了。

    private void ensureCapacityInternal(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}

这里可以很清楚地看出,

minCapacity - elementData.length > 0

这行代码检查了新增的元素位置是否超出了当前数组对象的最大长度,基于上面的假设,此判断是成立的,所以需要继续往下看,看grow()方法。

    private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
}

看第二行代码,newCapacity = oldCapacity + oldCapacity / 2;
就是说每次当发现当前数组长度不足时,每次增加的步长是【0.5倍的当前长度】。
Ps.注意这里有一个坑,假如增加长度后超出了Max_ARRAY_SIZE(jdk定义为maxIntValue-8),直接返回MaxIntValue。 最后就是调用Arrays.copyOf方法了,里面主要调用的是System.arrayCopy方法,是一个JNI调用,有兴趣的同学可以去JDk官网看底层的实现,这里就不多累赘了。 --------------------------------------------------------------------------------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------

接着来看看remove方法。
    public E remove(int index) {
rangeCheck(index); modCount++;
E oldValue = elementData(index); int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // Let gc do its work return oldValue;
}
remove就比较简单了,它的原理就是找到要删除的下标,假设数组[1,2,3,4,5]你要删除3,jdk的做法就是把[1,2]和[4,5]数组复制到原数组,形成新数组[1,2,4,5,5],
然后执行elementData[--Size]防止内存泄露,完毕~

总结:
ArrayList就是一个通过申请新内存来扩容的数组!

【Java集合类】ArrayList详解 (JDK7)的更多相关文章

  1. Java集合类的详解与应用

    Java集合类的详解与应用 集合简介: 1.定义:可以同时存储不同类型的数据 他的存储空间会随着数据的增大而增大 2.缺点:只能存储引用数据类型 3.优点:更加合理的利用空间,封装了更多的方法,用起来 ...

  2. java集合类,详解

    集合详解 1.1HashSet HashSet是Set接口的一个子类,主要的特点是:里面不能存放重复元素,而且采用散列的存储方法,所以没有顺序.这里所说的没有顺序是指:元素插入的顺序与输出的顺序不一致 ...

  3. Java.util.ArrayList详解

    java.util.ArrayList就是传说中的动态数组. 继承了关系,有此可看出ArrayList与list的collection的关系 public class ArrayList<E&g ...

  4. Java 8 ArrayList 详解

    GitHub Page: http://blog.cloudli.top/posts/Java-ArrayList/ ArrayList 继承于 AbstractList ,实现了 List.Rand ...

  5. java集合类图详解

  6. [转载]Java迭代器(iterator详解以及和for循环的区别)

    Java迭代器(iterator详解以及和for循环的区别) 觉得有用的话,欢迎一起讨论相互学习~[Follow] 转载自 https://blog.csdn.net/Jae_Wang/article ...

  7. ArrayList详解-源码分析

    ArrayList详解-源码分析 1. 概述 在平时的开发中,用到最多的集合应该就是ArrayList了,本篇文章将结合源代码来学习ArrayList. ArrayList是基于数组实现的集合列表 支 ...

  8. 转:Java HashMap实现详解

    Java HashMap实现详解 转:http://beyond99.blog.51cto.com/1469451/429789 1.    HashMap概述:    HashMap是基于哈希表的M ...

  9. java集合框架详解

    java集合框架详解 一.Collection和Collections直接的区别 Collection是在java.util包下面的接口,是集合框架层次的父接口.常用的继承该接口的有list和set. ...

随机推荐

  1. Delphi 中的常用事件

    OnActive 焦点称到窗体或控件时发生 OnClick 鼠标单击事件 OnDbClick 鼠标双击事件 OnClose和OnCloseQuery 当关闭一个窗体时就会响应OnClose和OnClo ...

  2. EhLib DBGridEh组件在Delphi中应用全攻略总结(转)

    EhLib DBGridEh组件在Delphi中应用全攻略总结(转) http://blog.sina.com.cn/s/blog_94b1b40001013xn0.html 优化SQL查询:如何写出 ...

  3. PHP Memcached 实现简单数据库缓存

    Memcache常用方法 Memcache::add — 添加一个值,如果已经存在,则返回false Memcache::addServer — 添加一个可供使用的服务器地址 Memcache::cl ...

  4. cookie、session、sessionid的区别

    我们都知道银行,银行的收柜台每天要接待客户存款/取款业务,可以有几种方案: 1.凭借柜台职员的记忆,由收柜台职员来为每位顾客办理存款/取款业务,单凭职员的记忆力,要记到每位顾客的相貌,并迅速这个顾客当 ...

  5. Spring EL中的类操作符

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://ww ...

  6. 前端自动化构建工具-yoman浅谈

    如今随着前端技术的飞速发展,前端项目也变得越来越复杂. 快速的搭建一个集成多种工具和框架的复杂前端项目也越来越成为一种需求. 当然如果你要自己从0开始完全自己diy,绝对可以,只不过需要耗费一些不少的 ...

  7. Nagios 系统监控基本安装配置过程详解

    Nagios 是一款免费的开源 IT 基础设施监控系统,功能强大,灵活性强,能有效监控 Windows.Linux.VMware 和 Unix 主机状态,交换机.路由器等网络设置等.一旦主机或服务状态 ...

  8. Oracle RAC学习笔记01-集群理论

    Oracle RAC学习笔记01-集群理论 1.集群相关理论概述 2.Oracle Clusterware 3.Oracle RAC 原理 写在前面: 最近一直在看张晓明的大话Oracle RAC,真 ...

  9. 照片提取GPS 转成百度地图坐标

    感谢: 小慧only http://www.cnblogs.com/zhaohuionly/p/3142623.html  GPS转化坐标方法 大胡子青松 http://www.cnblogs.com ...

  10. Android开发知识体系总结