java源码-ArrayList
开篇
ArrayList主要由如下特性:
ArrayList实际上是通过一个数组去保存数据的,当我们构造ArrayList时,如果使用默认构造函数,ArrayList的默认容量大小是10。
当ArrayList容量不足以容纳全部元素时,ArrayList会自动扩张容量,新的容量 = 1.5*原始容量。
ArrayList的克隆函数,将全部元素克隆到一个数组中,采用Arrays.copyOf方法实现。
ArrayList实现java.io.Serializable的方式。当写入到输出流时,先写入“容量”,再依次写出“每一个元素”;当读出输入流时,先读取“容量”,再依次读取“每一个元素”。
在做ArrayList的遍历的时候有3中遍历的方法,分别是随机访问遍历,用迭代器遍历和强制for循环遍历,按照效率来说最快的是随机访问遍历,最差的是迭代器遍历。
ArrayList的遍历是不安全的,在遍历的时候如果改变了集合的结构会抛出ConcurrentModificationException异常。
ArrayList类图
ArrayList类定义
ArrayList的类定义比较简单,基本上可以看出来默认值数组大小为10,数据存储通过elementData变量。
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable { private static final long serialVersionUID = 8683452581122892189L; // 默认初始化大小 private static final int DEFAULT_CAPACITY = 10; private static final Object[] EMPTY_ELEMENTDATA = {}; private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //默认是package-private access,保存数据 transient Object[] elementData; //实际保存的数据量大小 private int size; }
ArrayList构造函数
ArrayList的构造数非常简单,根据传入的参数initialCapacity初始化数组大小。如果不传参数就默认构建空数组。
public ArrayList(int initialCapacity) { if (initialCapacity > 0) { this.elementData = new Object[initialCapacity]; } else if (initialCapacity == 0) { this.elementData = EMPTY_ELEMENTDATA; } else { throw new IllegalArgumentException("Illegal Capacity: "+ initialCapacity); } } public ArrayList() { this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA; } public ArrayList(Collection<? extends E> c) { elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // replace with empty array. this.elementData = EMPTY_ELEMENTDATA; } }
ArrayList常用操作
ArrayList的add操作
ArrayList的add操作其实就是分两步走:
- 以size+1的大小去看下是否容纳的下新元素,否则就以1.5的原有空间扩容。
- 在扩容后的新数组的index位置插入新元素。
- grow()方法内部实现扩容和旧元素的拷贝,采用Arrays.copyOf(elementData, newCapacity)实现。
public boolean add(E e) { ensureCapacityInternal(size + 1); // Increments modCount!! elementData[size++] = e; return true; } public void add(int index, E element) { rangeCheckForAdd(index); ensureCapacityInternal(size + 1); // Increments modCount!! System.arraycopy(elementData, index, elementData, index + 1, size - index); elementData[index] = element; size++; } private void ensureCapacityInternal(int minCapacity) { if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) { minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity); } ensureExplicitCapacity(minCapacity); } private void ensureExplicitCapacity(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity); } 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); }
ArrayList的remove操作
ArrayList的remove操作分两步走:
- 将待移除的index往后的元素拷贝至index开始的位置。
- 将最后一位元素置null并且size-1即可。
ArrayList的clear操作负责将数组全部置null即可。
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; // clear to let GC do its work return oldValue; } public void clear() { modCount++; // clear to let GC do its work for (int i = 0; i < size; i++) elementData[i] = null; size = 0; }
ArrayList迭代器
ArrayList的迭代器实现很简单,通过创建Itr对象。在Itr类当中将cursor初始化为0,next过程中就是返回变量同时将cursor+1,hasNext()方法只是判断cursor是否等于size的值。
public Iterator<E> iterator() { return new Itr(); } private class Itr implements Iterator<E> { int cursor; // 默认初始化值为0 int lastRet = -1; // 上一个返回值的下标 int expectedModCount = modCount; public boolean hasNext() { return cursor != size; } public E next() { checkForComodification(); int i = cursor; if (i >= size) throw new NoSuchElementException(); Object[] elementData = ArrayList.this.elementData; if (i >= elementData.length) throw new ConcurrentModificationException(); cursor = i + 1; return (E) elementData[lastRet = i]; } }
参考文章

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
第7章—SpringMVC高级技术—不用web.xml,而使用java类配置SpringMVC
不用web.xml,而使用java类配置SpringMVC DispatcherServlet是Spring MVC的核心,按照传统方式, 需要把它配置到web.xml中. 我个人比较不喜欢XML配置方式, XML看起来太累, 冗长繁琐. 还好借助于Servlet 3规范和Spring 3.1的功能增强, 可以采用一种全新的,更简洁的方式配置Spring MVC了. 下面按这种方式一个Hello World的MVC配置. Step 1:先用idea创建一个Maven的WEB工程. pom.xml文件如下: OcrWebAppInitializer: package com.home.config; import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer; public class OcrWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {...
- 下一篇
技术重要吗?
今天看脉脉上面有些女的技术都是厉害得不行. 所以感觉去争论或者比较谁技术牛多牛没有什么实在的意义. 今天的记录是这样的. 1.首先我要做一个订单系统. 具体更多:https://deadzq.github.io/ 然后jQuery待加入,之前的JavaScript判定待整齐. 后来发现使用JSP的EL和JSTL接收request的传值实在是太恶心了.所以觉得学习JSON很有必要. 上面的input表示数量及+-按钮很粗糙. 具体代码可能看花了 <%@ page import="java.util.ArrayList" %> <%@ page import="com.ykmimi.order.entity.Foods" %> <%@ page import="com.ykmimi.order.entity.Customers" %><%-- Created by IntelliJ IDEA. User: SeeClanUkyo Date: 2018/07/19 Time: 22:31 To change this template use F...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- CentOS6,CentOS7官方镜像安装Oracle11G
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- SpringBoot2更换Tomcat为Jetty,小型站点的福音
- MySQL8.0.19开启GTID主从同步CentOS8
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Docker安装Oracle12C,快速搭建Oracle学习环境