博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
数据结构(一)ArrayList源码分析
阅读量:7235 次
发布时间:2019-06-29

本文共 4574 字,大约阅读时间需要 15 分钟。

一、相关特性:

1、关系图:

2、特点:

  • 元素所占存储空间是连续的
  • 基于数组实现,容量可自增
  • 可通过角标获取指定位置的元素
  • 查询快(基于数组索引),增删慢(涉及到数组复制、移动和扩容)

二、构造函数和变量:

1、变量:

public class ArrayList
extends AbstractList
implements List
, RandomAccess, Cloneable, java.io.Serializable { //首次默认扩展的值 private static final int DEFAULT_CAPACITY = 10; //空数组 private static final Object[] EMPTY_ELEMENTDATA = {}; //默认的elementData private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; //元素的存储结构为数组 transient Object[] elementData; //数组长度 private int size; ......复制代码

2、构造函数

(1)使用无参构造创建一个ArrayList,默认数组为空{}

public ArrayList() {	this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}复制代码

(2)可通过构造指定数组的大小

public ArrayList(int initialCapacity) {    if (initialCapacity > 0) {        this.elementData = new Object[initialCapacity];    } else if (initialCapacity == 0) {	    //如果传入0,数组为空数组        this.elementData = EMPTY_ELEMENTDATA;    } else {        throw new IllegalArgumentException("Illegal Capacity: "+                                           initialCapacity);    }}复制代码

(3)可传入一个集合

public ArrayList(Collection
c) { //转为数组,赋值给elementData elementData = c.toArray(); if ((size = elementData.length) != 0) { // c.toArray might (incorrectly) not return Object[] (see 6260652) //这个啥bug? if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); } else { // 空数组 this.elementData = EMPTY_ELEMENTDATA; }}复制代码

c.toArray might (incorrectly) not return Object[]:

List
dataList = new ArrayList
(); dataList.add("one"); dataList.add("two"); Object[] listToArray = dataList.toArray(); 复制代码

通过toArray转为Object数组(内部实现不同),但是listToArray不一定能放置Object对象,出现这种情况就通过Arrays.copyOf来创建一个Object数组,就可以存放任意类似的元素了。

三、添加元素:

1、队尾添加元素

  • 进行数据长度判断,不够进行扩容
  • 队尾插入元素
public boolean add(E e) {	//(1)扩容    ensureCapacityInternal(size + 1);  // Increments modCount!!    //(2)赋值    elementData[size++] = e;    return true;}复制代码

(1)扩容

private void ensureCapacityInternal(int minCapacity) {    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {	    //所需最小容量        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);    }    ensureExplicitCapacity(minCapacity);}private void ensureExplicitCapacity(int minCapacity) {    modCount++;    // 需要扩容了    if (minCapacity - elementData.length > 0)        grow(minCapacity);}private void grow(int minCapacity) {    // overflow-conscious code    int oldCapacity = elementData.length;    //1.5倍扩容    int newCapacity = oldCapacity + (oldCapacity >> 1);    //如果还不满足,直接扩容到minCapacity    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);}复制代码

扩容机制:

  • 创建一个空数组elementData,第一次插入数据时扩容到10
  • 如果elementData长度不够就直接扩容1.5倍
  • 如果还不够,就使用需要的长度作为elementData的长度

2、指定位置添加元素

  • 进行数据长度判断,不够进行扩容
  • 进行数组复制
  • 插入元素
public void add(int index, E element) {    if (index > size || index < 0)        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));	//(1)确保数组长度足够    ensureCapacityInternal(size + 1);  // Increments modCount!!	//(2)将数据向后移动一位    System.arraycopy(elementData, index, elementData, index + 1, size - index);    //(3)插入元素    elementData[index] = element;    size++;}复制代码

(1)数组扩容同上 (2)数组复制

* @param src  原数组 * @param srcPos 原数组要复制的开始位置 * @param dat 目标数组 * @param dstPos 目标数组的开始位置 * @param length 要复制的长度 *  /public static native void arraycopy(Object src, int srcPos,    Object dst, int dstPos, int length);复制代码

四、删除元素:

public E remove(int index) {    if (index >= size)        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    modCount++;    E oldValue = (E) elementData[index];    int numMoved = size - index - 1;    //数组前移    if (numMoved > 0)        System.arraycopy(elementData, index+1, elementData, index,                         numMoved);    //最后位置的元素置null    elementData[--size] = null; // clear to let GC do its work    return oldValue;}复制代码

五、修改元素:

public E set(int index, E element) {    if (index >= size)        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));	//获取当前位置元素    E oldValue = (E) elementData[index];    //当前位置置为新元素    elementData[index] = element;    return oldValue;}复制代码

六、获取元素:

public E get(int index) {    if (index >= size)        throw new IndexOutOfBoundsException(outOfBoundsMsg(index));    return (E) elementData[index];}复制代码

根据索引获取数组

转载地址:http://ntlfm.baihongyu.com/

你可能感兴趣的文章
2019年最全最系统的大数据学习路线
查看>>
【云周刊】第206期:2018年阿里云云攻略十二篇精选好文 ...
查看>>
面对“烟囱式”难题,联想企业网盘展现跨时空延展能力
查看>>
函数第一部分:经典的永远是简单的-Python基础前传(10)
查看>>
一个该死的Linux权限问题
查看>>
Oracle 中关于 Between and 日期边界问题
查看>>
7.5-7.8一周学习笔记
查看>>
小米首款三折叠屏手机曝光,折叠屏会是2019年热潮吗?
查看>>
云服务器能干什么
查看>>
PCIe-8604 USB3.0图像采集卡无需额外供电机器视觉智能相机网卡
查看>>
新版 Microsoft Edge 有时会假扮成不同浏览器
查看>>
redis hash底层数据结构
查看>>
H5移动前端开发常用高能css3汇总
查看>>
大规模特征构建实践总结
查看>>
java源码-LinkedList
查看>>
WPF 引用 ttf文件
查看>>
WPF自定义控件 使用阿里巴巴图标
查看>>
Window 远程桌面无法复制粘贴(转载)
查看>>
WPF中使用ReportViewer报表
查看>>
Java JimToMov(图片转视频)
查看>>