Java容器系列(二)ArrayList

一、简介

     ArrayList位于java.util包下,它继承于AbstractList,实现了List, RandomAccess, Cloneable, java.io.Serializable这些接口。基于数组实现,是一个动态的容器,与数组的大小一旦确定不能修改不同的是,ArrayList的容量大小可以动态的变化。
      ArrayList 实现了RandmoAccess接口,即提供了随机访问功能。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在ArrayList中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问;遍历ArrayList时,使用随机访问(即,通过索引序号访问)效率最高,而使用迭代器的效率最低!

ArrayList 实现了Cloneable接口,即覆盖了函数clone(),能被克隆。ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。

2.具体继承关系及直接子类

  • java.lang.Object
    • java.util.AbstractCollection<E>
      • java.util.AbstractList<E>
        • java.util.ArrayList<E>
  • All Implemented Interfaces:

Serializable , Cloneable , Iterable <E>, Collection <E>, List <E>, RandomAccess

已知直接子类:

AttributeList , RoleList , RoleUnresolvedList

3、根据源码  简写其原理

       由于是自己写的,可能跟源码中有些差异,但实现原理相同,易于理解,这里主要写一个ArrayList中最重要的几个方法,如

add(),get(int index),remove(int index)方法;

public class MyArrayList {

    // 定义动态数组,变量修饰符暂用private,

    // 源码用transient来修饰,

    // 用transient关键字标记的成员变

    // 量不参与序列化过程。

    private Object [] elementData;

    // 容器中所包含元素的个数

    private  int size;

    /**
     * 无参构造器,默认创建容量为10的动态数组,
     * 为了方便,这里不单独定义 DEFAULT_CAPACITY 了
     */

    public MyArrayList(){
        this(10);
    };

    /**

     * 有参构造器:

     *  创建arrayList对象的时候,可以指定初始化容器的大小

     * @param initialCapacity

     */
    public MyArrayList(int initialCapacity){
       if(initialCapacity<0) {
           try {
               throw new Exception();
           } catch (Exception e) {
               e.printStackTrace();
           }
       }
       elementData = new Object[initialCapacity];
   };

    /**

     *  size()方法,返回容器中元素个数

     * @return

     */
    public int size() {
        return size;
    };

    /**
     * add()方法,向容器中添加一个元素
     * 实现思路:
     *      1、需要判断当前容量的容器是否已经装满元素,
     *      若已经装满元素,则需要扩容
     *      (实际上就是创建一个容量为原来两倍的新数组,
     *       然后把旧数组中的元素再拷贝到新数组中,
     *       源码中是这样计算新数组的容量的:
     *       int newCapacity = oldCapacity + (oldCapacity >> 1);
     *       此处运用位运算,提高运算速度
     *        为了方便,我直接用原来的容量乘以2计算的。
     *      )
     *      否则,则直接将此元素添加到容器后则
     *      2、容器中元素的个数增加1
     * @param obj
     */
    public void add(Object obj) {
        if(size>=elementData.length) {//需要扩容
            // 此处创建
            Object[] newELementData = new Object[size*2];
//            public static void arraycopy(Object src, int srcPos,
//                           Object dest, int destPos, int length)
//            代码解释:
//               Object src : 原数组
//                 int srcPos : 从元数据的起始位置开始
//               Object dest : 目标数组
//               int destPos : 目标数组的开始起始位置
//               int length  : 要copy的数组的长度
            System.arraycopy(elementData,0,newELementData,
                    0,elementData.length);
            elementData = newELementData;
        }
        elementData[size++]=obj;
    };

    /**
     * isEmpty(),判断容器是否为空
     * @return
     */

    public boolean isEmpty() {
        if(size==0) {
            return  true;
        };
        return false;
    };

    /**
     * get(int index)方法
     *  实现思路:
     *      通过下标获取当前容器中相应位置的元素,
     *      首先需要判断传入的下标 是否合理,
     *         即是否是非负数,
     *      并且不能大于等于容器中的元素个数
     *      若果合理,则直接通过下标从数组中获取即可,
     *      若果不合理,
     *      则直接抛出异常,此处异常我没做详细处理
     * @param index
     * @return
     */
    public Object get(int index) {
        rangeCheck(index);
        return  elementData[index];
    };
    // 私有方法,检查下标是否合理,只在此类中使用
    private void rangeCheck(int index) {
        if(index<0 || index>=size) {
            try {
                throw  new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    /**
     * remove(int index)方法
     *  实现思路:
     *  1、首先判断传入参数是否合理,
     *      同get()方法中的判断逻辑;
     *  2、拷贝原数组中index之后的 size-index-1个
     *      元素到index位置及之后
     *  3、容器中元素的个数减1
     * @param index
     */

    public void remove (int index) {
        rangeCheck(index);
        // index位置之后的size-index-1个元素
        int numMoved = size - index - 1;
        if(numMoved>0) {
            System.arraycopy(elementData,index+1,elementData,index,numMoved);
        };
        elementData[--size] =null;
    }
    
}

四,总结

       说白了,arrayList就是一个数组,只是这个数组可以根据情况增加容量。

     以上代码如有错误之处,请各位仁兄批评指正,下一节我会总结linkedList的源码实现过程。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值