美文网首页
集合-AarrayList

集合-AarrayList

作者: 8813d76fee36 | 来源:发表于2018-04-23 15:46 被阅读7次

简介

ArrayList是Java中对表ADT的一种可增长数组实现。
通过数组索引使其执行get(获取某索引对应的元素)和set(替换某索引对应的元素)效率高;而执行add(在某处添加元素)和remove(移除某处元素)效率较低(对应元素后的所有元素的位置都需要后推或前移),除非是对末端元素的操作。

成员变量

  • 默认初始化容量为10。
private static final int DEFAULT_CAPACITY = 10;
  • 用于空实例的共享空数组实例
private static final Object[] EMPTY_ELEMENTDATA = {};
  • 用于默认大小的空实例的共享空数组实例。用于添加第一个元素时判断数组需要扩充多少。
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  • 用于存储ArrayList元素的缓冲数组。ArrayList的容量(capacity)就是该缓冲数组的大小(size)。任何elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA形式的空ArrayLis的容量在第一个元素添加进来后都会扩充为DEFAULT_CAPACITY
transient Object[] elementData;
  • ArrayList的大小(size),指的是ArrayList中包含的元素的个数。
private int size;

容量(capacity)指ArrayList最大能存放多少个元素。
大小(size)指ArrayList当前存储的元素的个数。

初始化一个ArrayList

ArrayList提供了三种构造方式。

  1. 无参构造
    构造一个空的ArrayList,容量为10。
public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

API使用

add(Object obj)

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

add()方法主要有三个任务。

  1. 确定容量,并将修改数+1。(modCount,表示对该集合的操作次数。)
ensureCapacityInternal(size + 1);  // Increments modCount!!
  1. 添加新元素
elementData[size++] = e;
  1. 返回true
 return true;

其中确定容量的操作是add()方法的核心。详细步骤如下:

  1. 将集合当前的大小+1作为最小容量(minCapacity)传入ensureCapacityInternal()方法。
  2. 调用int calculateCapacity(Object[] elementData, int minCapacity)方法,计算集合扩容后的容量。
private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }

首先判断当前缓冲数组是否为DEFAULTCAPACITY_EMPTY_ELEMENTDATA类型,如果是,则调用Math.max(DEFAULT_CAPACITY, minCapacity);方法在默认容量(10)与最小容量(minCapacity)两者之间取较大者作为缓冲数组的容量。
如果不是DEFAULTCAPACITY_EMPTY_ELEMENTDATA类型则直接使用最小容量作为数组扩容后的容量。

  1. 调用private void ensureExplicitCapacity(int minCapacity)方法。
private void ensureExplicitCapacity(int minCapacity) {
        //累加一次修改数
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity); //该方法为扩容操作的具体实现
    }
  1. 调用private void grow(int 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新增元素的实际操作是将内部的缓冲数组复制到更大容量的新数组中,该操作是使用Arrays.copyof()实现的

remove(Object obj)

public boolean remove(Object o) {
        if (o == null) {
            for (int index = 0; index < size; index++)
                if (elementData[index] == null) {
                    fastRemove(index);
                    return true;
                }
        } else {
            for (int index = 0; index < size; index++)
                if (o.equals(elementData[index])) {
                    fastRemove(index);
                    return true;
                }
        }
        return false;
    }

remove()方法有两步主要操作

  1. 使用for循环遍历缓冲数组elementData,找到需要删除的元素的下标。
    若需要删除null元素,则使用elementData[index] == null;若不为null,则使用o.equals(elementData[index])
  2. 调用fastRemove()方法删除元素。

其中fastRemove()方法为实现删除的关键操作

private void fastRemove(int index) {
        modCount++;
        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
    }
  1. 将操作数(modCount)加1;
  2. 计算要移动的元素数量。
  3. 调用System.arraycopy()得到除去指定删除元素后的新数组。
    这步操作是将被删除元素后的所有元素,从被删除元素的下标位置开始复制,得到新数组。
  4. 上一步复制操作结束后,数组最后一个元素会重复,通过elementData[--size] = null;删除它,让GC回收。
    删除1
    执行System.arraycopy()前
    执行System.arraycopy()前后
    此时I元素已被它后面的五个元素替换,并在最后多处来一个末尾元素。
    elementData[--size] = null; 多出的末尾元素被去除,得到新数组

相关文章

  • 集合-AarrayList

    简介 ArrayList是Java中对表ADT的一种可增长数组实现。通过数组索引使其执行get(获取某索引对应的元...

  • 我的Swift的学习总结 -->第二周

    集合 集合:Set,定义一个集合可以写成:var 集合名 : Set<集合类型> = [集合元素],具体的集合应用...

  • markdown 测试

    集合 集合 集合 引用

  • kotlin学习第五天:集合,高阶函数,Lambda表达式

    集合 list集合 list集合分为可变集合与不可变集合。由list of创建的集合为不可变集合,不能扩容,不能修...

  • kotlin练习 ---- 集合练习

    kotlin练习 - 集合练习 Set集合 Set集合创建 Set集合的使用 List集合 List集合创建 Li...

  • 集合总结

    集合 集合分为单列集合和双列集合两种: 一.单列集合: Collection是单列集合的顶级接口: 其中有三类集合...

  • 映射、元组、集合

    映射 元组 集合 集合之seq 集合之set 集合之map

  • 16.Collection集合

    主要内容: Collection 集合 迭代器 增强for List 集合 Set 集合 1,集合 集合是java...

  • 集合与有序集合

    集合分为有序集合 (zset) 和无序集合 (set), 一般无序集合也直接说成集合 无序集合 (set) 无序集...

  • python入坑第八天|集合

    好的,各位蛇友,我们今天来学习集合。 内容: 集合的创建 集合操作符号 集合的内置函数 集合的创建 集合用set(...

网友评论

      本文标题:集合-AarrayList

      本文链接:https://www.haomeiwen.com/subject/qtwqlftx.html