ArrayList

ArrayList是List接口的一个子类,它在底层通过一个数组实现了数据的存储,相比于普通的数组而言,ArrayList的长度可变,这是它的一大优点。ArrayList中的数据是有序可重复的,下面来看看ArrayList的一些基本属性和方法以及简单Integer型ArrayList的自己实现。



1.基本属性与特点

·通过查询源码可以看出其底层数组的默认初始化大小为10:
这里写图片描述
·其数组的扩容方式是扩大为当前数组长度的1.5倍
这里写图片描述
·ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
·ArrayList中的操作不是线程安全的,所以,建议在单线程中才使用ArrayList。
·ArrayList包含了两个重要的对象:elementData 和 size,elementData 是”Object[]类型的数组”,它保存了添加到ArrayList中的元素,size 则是动态数组的实际大小。
这里写图片描述



2.基本常用方法

·add()添加元素,当参数为元素时返回值是boolean型,当参数是下标和元素时无返回值,其时间复杂度是O(1)

        ArrayList<Integer> array = new ArrayList<>();
        // 插入到数据的最后
        array.add(1);
        // 插入到指定的1号位置,原1号及其以后位置元素一次后迁一位
        array.add(1, 2);

注:在ecalipse中要求右边也要写上数据类型,即ArrayList<Integer> array = new ArrayList<Integer>(); 但是在IDEA中不需要,我用的是IDEA,所以都不再写。

·addAll()将一个集合添加到指定集合,返回值是boolean型

        ArrayList<Integer> array1 = new ArrayList<>();
        ArrayList<Integer> array2 = new ArrayList<>();
        // 将集合2中的元素依次尾插到集合1中
        array1.addAll(array2);
        // 将集合2中的元素从集合1的2号位置开始依次插入。集合1的元素对应后移
        array1.addAll(2, array2);

·remove()删除元素,当参数是索引时,返回值是想要删除的元素,当参数是元素时,返回值是boolean型,其时间复杂度是O(1)


         // 当参数为int型时,哪怕你的初衷是想删除数据2,但是系统会将2当做索引处理,
         // 所以当集合中存储的是int型的数据的时候,只能通过索引的方式来删除数据
          array.remove(2);

·removeAll(C c)从array中删除其包含集合array1的所有元素,返回值是boolean

        array.removeAll(array1);

·clear()清空集合,无返回值

        arra.clear();

·retainAll(C c)保留集合array与array1共有的元素,返回值是boolean型

        array.retainAll(array1);

·contains(O o)是否包含指定元素,返回值是boolean型

        array.contains(2);

·get(int index)获取指定元素,其时间复杂度是O(1)

        array.get(2);

·set()用指定元素替换指定位置的元素,并返回旧值,其时间复杂度是O(1)

        // 用5替换2号位置的元素,返回旧值
        array.set(2, 5);


3.ArrayList的迭代器

迭代器是一种提供对容器进行访问的方法,而不暴露容器内部细节的工具,它的内部有hasNext()、next()和remove()方法,一般的使用格式为:

        Iterator<Integer> integer = array.iterator();
          while (integer.hasNext()){
            System.out.print(integer.next() + " ");
        }

注意在迭代的时候不能对数据进行任何修改,即

        Iterator<Integer> integer = array.iterator();
          while (integer.hasNext()){
            array.add(1);
            array.remove(2);
            System.out.print(integer.next() + " ");
        }

以上操作会抛出异常,源码中有如下代码:

    private class Itr implements Iterator<E> {
        int cursor;       // index of next element to return
        int lastRet = -1; // index of last element returned; -1 if no such
        int expectedModCount = modCount;
        public boolean hasNext() {
            return cursor != size;
        }

其中expectedModCount记录的是当前的迭代器号,每当对数据进行一次操作,expectedModCount都会加1,所以在迭代器中对数据进行操作,expectedModCount就会改变,由于前后expectedModCount不一致,就会导致出错。



总结:

    ·ArrayList集合适用于对大型数据的查询操作,因为其底层是一个数组,由于索引的存在而查询便捷
    ·removeAll(C c)方法可以用于求两个集合的差集
    ·retainAll(C c)方法可以求两个集合的交集
    ·addAll(C c)方法可以求两个集合的并集
    ·使用迭代器遍历集合时严禁修改数据,此条适用于所有Collection集合。


4.ArrayList的简单实现

import java.util.Arrays;

/**
 * description:实现ArrayList
 *
 * @author ajie
 */
class MyArrayList<T> {
    /**
     * 默认初始容量
     */
    private static final int MENDACITY = 10;
    /**
     * 底层数组
     */
    private int[] array;
    /**
     * 容量
     */
    private int size;

    /**
     * 无参构造函数
     */
    public MyArrayList() throws Exception {
        this(MENDACITY);
    }

    /**
     * 指定容量构造函数
     *
     * @param capacity
     * @throws Exception 非法容量
     */
    public MyArrayList(int capacity)throws Exception {
        if (capacity < 0) {
            throw new Exception("error capacity!");
        }
        this.size = -1;
        this.array = new int[capacity];
    }

    /**
     * 添加元素
     *
     * @param value
     */
    public void add(Integer value) {
        if (size < array.length - 1) {
            array[++size] = value;
        } else {
            array = Arrays.copyOfRange(array, 0, (3 * array.length) >> 1);
            array[++size] = value;
        }

    }

    /**
     * 添加数组
     *
     * @param arr
     */
    public void addAll(int[] arr) {
        if (array.length - 1 > size + arr.length) {
            System.arraycopy(arr, 0, array, size + 1, arr.length);
        } else {
            array = Arrays.copyOfRange(array, 0, size + 1 + arr.length);
            System.arraycopy(arr, 0, array, size + 1, arr.length);
        }
        size = size + arr.length;
    }

    /**
     * 默认删除
     *
     * @return
     */
    public int remove() {
        if (array.length == 0) {
            return -1;
        }
        int val = array[size];
        array[size--] = -1;
        return val;
    }

    /**
     * 指定下标删除
     *
     * @param index
     * @throws Exception 非法下标
     */
    public boolean remove(int index) throws Exception {
        if (array.length == 0 || index < 0 || index > size) {
            throw new Exception("error index!");
        } else {
            for (int i = index; i < array.length - 1; i++) {
                array[i] = array[i + 1];
            }
            array[size--] = -1;
            return true;
        }
    }

    /**
     * 修改
     *
     * @param index
     * @param val
     * @return
     * @throws Exception 角标越界
     */
    public int set(int index, Integer val) throws Exception {
        if (index < 0 || index > size) {
            throw new Exception("out of array boundary!");
        }
        int oldValue = array[index];
        array[index] = val;
        return oldValue;
    }

    /**
     * 获取
     *
     * @param index
     * @return
     */
    public int get(int index) {
        return (index < 0 || index > size) ? -1 : array[index];
    }

    public void print() {
        for (int i = 0; i <= size; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
}

注:以上使用的API版本为JDK1.7.0_81

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值