相信对于使用过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. mysql 常用技巧

    1.正则使用 比 LIKE 会牺牲很多的系统资源 尽量不要用 正则的语法和JS PHP 差不多 select * from t1 where email REGEXP "@163[,.]co ...

  2. 【翻译】在Visual Studio中使用Asp.Net Core MVC创建第一个Web Api应用(二)

    运行应用 In Visual Studio, press CTRL+F5 to launch the app. Visual Studio launches a browser and navigat ...

  3. Java中正则表达式的几种用法

    多数内容转载自:http://www.jb51.net/tools/regex.htm ,有改动 用到了java.util.regex包: 1. 验证 Pattern pattern = Patter ...

  4. 分析NGINX 健康检查和负载均衡机制

    nginx 是优秀的反向代理服务器,这里主要讲它的健康检查和负载均衡机制,以及这种机制带来的问题.所谓健康检查,就是当后端出现问题(具体什么叫出现问题,依赖于具体实现,各个实现定义不一样),不再往这个 ...

  5. oracle取字符串长度的函数length()和hengthb()

    http://blog.itpub.net/161195/viewspace-613263/ lengthb(string)计算string所占的字节长度 :返回字符串的长度,单位是字节 length ...

  6. SuperSocket入门(二)- 探索AppServer、AppSession,Conmmand和App.config

          在上一篇文章中,我们已经了解到了如何在SuperSocket处理客户端请求. 同时我们可能会发现一个问题,如果我们的服务器端包含有很多复杂的业务逻辑,这样的switch/case代码将会很 ...

  7. CSS页面渲染优化属性will-change

    前面的话   当我们通过某些行为(点击.移动或滚动)触发页面进行大面积绘制的时候,浏览器往往是没有准备的,只能被动使用CPU去计算与重绘,由于没有事先准备,应付渲染够呛,于是掉帧卡顿.而CSS属性wi ...

  8. Backdoor CTF 2013: 电子取证 250

    0x00 题目 h4x0r厌烦了你对他的城堡的所有攻击,所以他决定报复攻击你,他给你发来一封带有图片的邮件作为警告,希望你能找出他的警告消息:-) 消息的MD5值就是flag. 0x01 解题法1 给 ...

  9. 多线程——NSThread

    创建和启动线程 一个NSThread对象就代表一条线程 // 创建.启动线程 NSThread *thread = [[NSThread alloc] initWithTarget:self sele ...

  10. Accessibility辅助功能--一念天堂,一念地狱

    0x00什么是Accessibility(辅助功能) 考虑到部分用户不能很好地使用Android设备,比如由于视力.身体.年龄方面的限制,造成阅读内容.触控操作.声音信息等方面的获取困难,Androi ...