ArrayList

ArrayList简介

ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用ensureCapacity操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。

它继承于 AbstractList,实现了 List, RandomAccess, Cloneable, java.io.Serializable 这些接口。

在我们学数据结构的时候就知道了线性表的顺序存储,插入删除元素的时间复杂度为O(n),求表长以及增加元素,取第 i 元素的时间复杂度为O(1)

  ArrayList 继承了AbstractList,实现了List。它是一个数组队列,提供了相关的添加、删除、修改、遍历等功能。

  ArrayList 实现了RandmoAccess 接口,即提供了随机访问功能。RandmoAccess 是 Java 中用来被 List 实现,为 List 提供快速访问功能的。在 ArrayList 中,我们即可以通过元素的序号快速获取元素对象,这就是快速随机访问。

  ArrayList 实现了Cloneable 接口,即覆盖了函数 clone(),能被克隆。

  ArrayList 实现java.io.Serializable 接口,这意味着ArrayList支持序列化,能通过序列化去传输。

  和 Vector 不同,ArrayList 中的操作不是线程安全的!所以,建议在单线程中才使用 ArrayList,而在多线程中可以选择 Vector 或者 CopyOnWriteArrayList。

ArrayList核心代码分析

System.arraycopy()和Arrays.copyOf()方法

首先观察先System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length)的声明:

public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

src - 源数组。

srcPos - 源数组中的起始位置。

dest - 目标数组。

destPos - 目标数据中的起始位置。

length - 要复制的数组元素的数量。

该方法是用了native关键字,调用的为C++编写的底层函数,可见其为JDK中的底层函数。
再来看看Arrays.copyOf();该方法对于不同的数据类型都有相应的方法重载。

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

由U类型复制为T类型?

original - 要复制的数组

newLength - 要返回的副本的长度

newType - 要返回的副本的类型

public static int[] copyOf(int[] original, int newLength) {
        int[] copy = new int[newLength];
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

观察其源代码发现copyOf(),在其内部创建了一个新的数组,然后调用arrayCopy()向其复制内容,返回出去。
总结:

1.copyOf()的实现是用的是arrayCopy();

2.arrayCopy()需要目标数组,对两个数组的内容进行可能不完全的合并操作。

3.copyOf()在内部新建一个数组,调用arrayCopy()将original内容复制到copy中去,并且长度为newLength。返回copy;

ArrayList扩容技术

参考
- ArrayList 动态扩容机制
总结下,ArrayList 有一个初始的容量大小 10,当存储进里面的元素个数超过容量时,就需要增加 ArrayList 存储空间。每次要增加存储空间时,ArrayList 扩容到原来的 1.5 倍,并且进行复制操作,这个是非常伤性能的。如果 ArrayList 很大,执行数百次扩容,那么就会进行更多次数的新数组分配操作,以及更多次数的旧数组回收操作。

自己实现ArrayList


/**
 * @desc:自己实现ArrayList
 */
public class CustomArrayList {
    //存放元素的数组
    private Object[] elementData;
    //元素的个数
    private int size;
    //初始容量
    private static final int DEFAULT_CAPACITY = 3;

    public CustomArrayList() {
        this(DEFAULT_CAPACITY);
    }

    public CustomArrayList(int initCapacity) {
        if (initCapacity < 0) {
            throw new IllegalArgumentException("Illegal Capacity: " +
                    initCapacity);
        }
        elementData = new Object[initCapacity];
    }

    /**
     * 添加元素
     *
     * @param o
     */
    public void add(Object o) {
        ensureCapacity();
        elementData[size++] = o;
    }

    /**
     * 指定位置添加元素
     *
     * @param index
     * @param obj
     */
    public void add(int index, Object obj) {
        rangeCheck(index);
        ensureCapacity();
        // a b c d
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = obj;
        size++;
    }

    /**
     * 获取指定位置元素
     *
     * @param index
     * @return
     */
    public Object get(int index) {
        rangeCheck(index);
        return elementData[index];
    }

    /**
     * /删除指定位置的元素
     *
     * @param index
     */
    public void remove(int index) {
        rangeCheck(index);
        //a b c d
        //移动元素的个数
        int numMoved = size - index - 1;
        if (numMoved > 0)
            System.arraycopy(elementData, index + 1, elementData, index, numMoved);
        elementData[--size] = null;//Let gc and its work
    }

    /**
     * 删除指定元素
     *
     * @param o
     */
    public void remove(Object o) {
        for (int i = 0; i < size; i++) {
            if (get(i).equals(o)) {
                remove(i);
            }
        }
    }

    /**
     * @param index
     * @param o
     * @return
     */
    public Object set(int index, Object o) {
        rangeCheck(index);
        Object oldValue = elementData[index];
        elementData[index] = o;
        return oldValue;
    }

    /**
     * 数组扩容
     */
    private void ensureCapacity() {
        if (size == elementData.length) {
            Object[] newArray = new Object[size * 2 + 1];
            System.arraycopy(elementData, 0, newArray, 0, elementData.length);
            elementData = newArray;
        }
    }

    public int size(){
        return size;
    }

    private void rangeCheck(int index) {
        if (index < 0 || index > size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

    private String outOfBoundsMsg(int index) {
        return "Index: " + index + ", Size: " + size;
    }


    public static void main(String[] args) {
        CustomArrayList list = new CustomArrayList();
        list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        System.out.println(list.size());
        list.add(2,"插入元素");
        System.out.println(list.get(2));
        list.remove("插入元素");
        System.out.println(list.get(2));
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值