01.Java数据结构与算法之ArrayList

01.Java数据结构与算法之ArrayList

ArrayList底层原理细节

         ArrayList底层结构是一个长度可以动态增长的数组(顺序表)

 public Object []elementData; 

特点:

         在内存中分配连续的空间,只存储数据,不存储地址信息。位置就隐含着地址。

优点:

         1.节省存储空间,因为分配给数据的存储单元全用存放结点的数据(不考虑c/c++语言中数组需指定大小的情况), 结点之间的逻辑关系没有占用额外的存储空间。

         2. 索引查找效率高,即每一个结点对应一个序号,由该序号可以直接计算出来结点的存储地址。 假设线性表的每个数据元素需占用K个存储单元,并以元素所占的第一个存储单元的地址作为数据元素的存储地址。 则线性表中序号为i的数据元素的存储地址LOC(a i )与序号为i+1 的数据元素的存储地址LOC(a i+1 )之间的关系为
                  LOC(a i+1 ) = LOC(a i ) + K
通常来说,线性表的i号元素a i 的存储地址为
                  LOC(a i ) = LOC(a 0 ) + i×K
其中LOC(a 0 )为 0 号元素a 0 的存储地址,通常称为线性表的起始地址。

缺点:

        1.插入和删除操作需要移动元素,效率较低。

        2.必须提前分配固定数量的空间,如果存储元素少,可能导致空闲浪费。

        3.按照内容查询效率低,因为需要逐个比较判断

无参构造(一开始如果用户没设置集合大小,初始值就为10)
public ArrayList(){
        this(10);       //数组大小初始为10
    }
有参构造(给用户设置大小)
    public ArrayList(int len){
        elementData = new Object[len];
    }
集合容量不足时,每次扩容增加50%
    void grow(){
        //创建新的数组
        Object []newArr = new Object[elementData.length + (elementData.length >> 1)];//扩容1.5倍
        for(int i = 0; i < size; i++){
            //将原来数组的内容存到新数组里
            newArr[i] = elementData[i];
        }
        elementData = newArr;
    }
定义List接口
public interface List <T>{
    // ------- 添加 -------
    void add(Object object);

    // ------- 根据坐标删除 -------
    void remove(int index);

    // ------- 根据内容删除 -------
    void removeobj(Object object);

    // ------- 取出数据 -------
    Object get(int index);

    // ------- 求集合的长度 -------
    int size();

    // ------- 判断集合是否为空 -------
    boolean isEmpty();

    // ------- 根据内容找到元素坐标 -------
    int IndexOf(Object object);

    // ------- 判断元素是否存在 -------
    boolean contions(Object object);

    // ------- 根据坐标位置插入元素 -------
    void add(int index, Object object);

    // ------- 修改元素 -------
    void replase(int index, Object object);

    // ------- toString -------
    String toString();

    // ------- arraylist迭代器 -------
    ArrayList.Ite iterator();
}

定义Iterator接口
public interface Iterator <T>{
    boolean hasNext();
    T next();
}
ArrayList实现类
public class ArrayList <T>implements List {
    public Object []elementData;       //数组的引用
    private int size;                   //集合的大小,并非elementData.length
    //如果用户没设置大小就初始为10
    public ArrayList(){
        this(10);       //数组大小初始为10
    }
    //集合的大小等于用户设置的大小
    public ArrayList(int len){
        elementData = new Object[len];
    }

    // 数组的扩容
    void grow(){
        //创建新的数组
        Object []newArr = new Object[elementData.length + (elementData.length >> 1)];//扩容1.5倍
        for(int i = 0; i < size; i++){
            //将原来数组的内容存到新数组里
            newArr[i] = elementData[i];
        }
        elementData = newArr;
    }
	//在集合的尾部添加元素
    public void add(Object object) {
        //如果数组长度不够就调用扩容
        if(elementData.length <= size){
            grow();
        }
        elementData[size] = object;
        //大小增加一位
        size++;
    }
    //根据坐标删除元素
 	public void remove(int index) {
        //判断用户是否输入错误
        if(index<0|| index >size-1){
            throw  new IndexOutOfBoundsException("索引越界"+index);
        }
        Object element=elementData[index];
        // 向前移动元素
        for (int i = index; i <size-1 ; i++) {
            elementData[i]=elementData[i+1];
        }
        // 最后一个元素置为空
        elementData[size-1]=null;
        size--;
    }
    //根据元素删除
    public void removeobj(Object object) {
        int index = IndexOf(object);
        //判断用户是否输入错误!
        if(index<0){
            throw new NullPointerException();
        }
        remove(index);
    }
    //根据坐标得到元素
    public Object get(int index) {
        return elementData[index];
    }
    //求集合的长度
    public int size() {
        return size;
    }
    //判断是否为空
    public boolean isEmpty() {
        return size == 0;
    }
    //根据元素找到坐标
    public int IndexOf(Object object) {
        int i = 0;
        while(i < size){
            if(elementData[i].equals(object)){
                break;
            }
            i++;
        }
        return i;
    }
    //判断元素是否存在
    public boolean contions(Object object) {
        boolean flag = false;
        for(int i = 0; i < size; i++){
            if(elementData[i].equals(object)){
                flag = true;
                break;
            }
        }
        return flag;
    }
    //根据坐标位置添加元素
    public void add(int index, Object object) {
        if(size >= elementData.length){
            grow();
        }
        for(int i = size; i > index; i--){
            elementData[i] = elementData[i - 1];
        }
        elementData[index] = object;
        size++;
    }
    //修改元素
    public void replase(int index, Object object) {
        elementData[index] = object;
    }
    //重写toString
    public String toString(){
        StringBuilder str = new StringBuilder("[");
        for(int i = 0; i < size; i++){
            //判断是否到了最后一位,如果到了就不添加,
            if(i == size - 1){
                str.append(elementData[i]);
                break;
            }else{
                str.append(elementData[i] + ",");
            }
        }
        str.append("]");
        return str.toString();
    }

    // ------- 迭代器 -------
    public Ite iterator(){
        return new Ite();
    }

    public class Ite<T>implements Iterator<T> {
        int cursor = 0; //指向当前元素,默认是0
        public ArrayList arr = new ArrayList();

        public boolean hasNext() {
            return cursor != size;
        }

        public T next() {
            int i = cursor; //保留当前值
            cursor++;//自增
            // 进行判断,防止越界
            if (i > size) {
                throw new RuntimeException("没有元素");
            }
            return (T) elementData[i];
        }
    }
}

自定义异常(不自定义也没关系,java自带也有)
public class IndexOutOfBoundsException extends RuntimeException{
    public IndexOutOfBoundsException() {   }
    public IndexOutOfBoundsException(String message) {
        super(message);       
    }
}

猜你喜欢

转载自blog.csdn.net/qq_41424688/article/details/106222605