Java-ArrayList(动态数组)实现

Java-ArrayList(动态数组)底层源码实现过程

1. 首先定义一个List接口:

	对于一个动态数组来说,我们需要定义如下功能(由于我们不确定将来未来数据的类型,所以我们在这里采用泛型,并且让):
	*(1)void add(E element);  【在表尾添加元素】
	*(2)void add(int index, E element);【在指定索引添加元素】
	*(3)void remove(E element);【删除指定元素】
	*(4)E remove(int index);【删除指定角标的值并返回】
	*(5)E get(int index);【获取指定角标的值】
	*(6)E set(int index, E element);【修改指定角标的值并返回】
	*(7)int size();【获取线性表中有效元素个数】
	*(8)int indexOf(E element);【获取元素第一次出现的位置】
	*(9)boolean contains(E element);【是否包含某个元素】
	*(10)boolean isEmpty();【判空】
	*(11)void clear();【清空线性表】
	*(12)void sort(Comparator<E> c);【按照比较器的内容进行排序】
	*(13)List<E> subList(int fromIndex, int toIndex);【获取子线性表=》“左闭右开”】

具体实现:

首先我们先让我们自己创建的ArrayList实现我们自己定义的List接口,接着定义其成员变量:1.data数组 2.size(表示有效元素的个数、下一个元素插入的位置)

(1)在表尾添加元素:void add(E element):
    @Override
    public void add(E element) {
        add(size, element);//直接复用add(size,element)方法
    }
(2)在指定位置上添加元素:void add(int index, E element)
public void add(int index, E element){
	//在指定位置上添加元素,首先判断角标是否合法
	if(index < 0 || index > size){
		//角标不合法,抛出异常
		throw new IllegalArgumentException("add index out of range");
	}
	//角标合法,判断线性表是否已满
	if(size == data.length){
		//size表示有效元素个数,此时个数等于数组长度,表明已满
		resize(2 * data.length);//数组已满,调用扩容,长度为原数组的两倍
		//此处的resize方法并非是接口的,是我们ArrayList内部的
	}
	//扩容之后,将插入点之后的元素,向后移动[从后向前]
	for(int i = size - 1; i >= index; i-- ){
		data[i-1] = data[i];
	}
	//插入新元素
	data[index] = element;
	size++;
}
对数组的扩容、缩容方法进行实现:void resize(int newLen):
private void resize(int newLen){
//扩容、缩容方式不应该向外界提供,声明为私有
	E[] data = (E)(new Object[newLen]);
	//定义一个长度为newLen的新数组
	for(int i = 0; i < size; i++){
		newData[i] = data[i];//复制元素
	}
	data = newData;//将新数组地址赋值给data
}
(3)删除指定元素:void remove(E element):
public void remove(E element){
	int index = indexOf(element);
	if(index != -1){
		remove(index);
	}
}
(4)移除指定元素并返回:E remove(int index)
public E remove(int index){
	if(index < 0 || index >= size){
		throw new IllegalArgumentException("remove index out of range ");
	//保存要删除的值,以便返回
	E ret = data[index];
	//移动元素
	for(int i = index + 1; i < size; i++){
			data[i-1] = data[i];
		}
	}
	size--;
}
//缩容时机
//有效元素是容量的1/4并且当前容量必须大于默认容量
if(size == data.length / 4 && data.length > DEFAULT_CAPACITY){
	resize(data.length / 2);
}
return ret;
(5)E get(int index):获取指定角标的值
public E get(int index){
	if(index < 0 || index >= size){
		throw new IllegalArguementException("get index out of range");
	}
	return data[index];
}
(6)E set(int index, E element):修改指定角标的值并返回
public E set(int index, E element){
	if(index < 0 || index >= size){
		throw new IllegalArgumentException("set index out of range");
	}
	E ret = data[index];//此处声明为E,因为不确定未来ArrayList传入的数据类型
	data[index] = element;
	return ret; 
}
(7)int size():获取线性表中有效元素个数
public int size(){
	return size;
}
(8)int indexOf(E element):获取元素第一次出现的位置
public int indexOf(E element){
	for(int i = 0; i < size; i++){
		if(data.equals(element)){
			return i;//使用equals,可能传入的是引用数据类型
		}
	}
	return -1;//表明没有找到
}
(9)boolean contains(E element);【是否包含某个元素】
public boolean contains(E element){
	return indexOf(element) != -1;
}
(10)boolean isEmpty();【判空】
public boolean isEmpty(){
	return size == 0;
}
(11)void clear();【清空线性表】
public void clear(){
	data = (E[])(new Object[DEAULT_CAPACITY]);//直接让data指向新的数组
	size = 0;
}
(12)void sort(Comparator c);【按照比较器的内容进行排序】
public void sort(Comparator<E> c){
	if(c == null){
		throw new IllegalArgumentException("comparator can not be null");
	}
	//排序我们采用优化后的插入排序
	for(int i = 1; i < size; i++){
		
	}
}
(13)List subList(int fromIndex, int toIndex);【获取子线性表=》“左闭右开”】
public List<E> subList(fromIndex, int toIndex){
	if(fromIndex < 0 || toIndex >= size || fromIndex > toIndex){
		throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
	}
	ArrayList<E> list = new ArrayList<>();
	for(int i = fromIndex; i <= toIndex; i++){
		list.add(data[i]);
	}
	return list;
}

接下来是全部代码:
1.实现List接口:

package p1.接口;

import java.util.Comparator;

//线性表接口定义
public interface List<E> extends Iterable<E> {
    //默认在表尾添加一个元素
    public void add(E element);
    //在指定角标处添加元素
    public void add(int index, E element);
    //删除指定元素
    public void remove(E element);
    //删除指定角标处的元素 并返回原先的值
    public E remove(int index);
    //获取指定角标处的元素
    public E get(int index);
    //修改指定角标index处的值为element,并返回原先的值
    public E set(int index, E element);
    //获取线性表中的元素个数
    public int size();
    //查看元素第一次出现的角标位置(从左到右)
    public int indexOf(E element);
    //判断是否包含元素
    public boolean contains(E element);
    //判断线性表是否为空
    public boolean isEmpty();
    //清空线性表
    public void clear();
    //按照比较器的内容进行排序
    public void sort(Comparator<E> c);
    //获取子线性表 原线性表中[formIndex, toIndex)这个部分
    public List<E> subList(int fromIndex, int toIndex);

}

2.实现ArrayList:

package p2.线性结构;

import p1.接口.List;

import java.util.Comparator;
import java.util.Iterator;

//自定义的线性表的顺序存储方式
public class ArrayList<E> implements List<E> {
    //定义数组的容器 data.length 指的就是当前数组的容量
    private E[] data;
    //元素的个数 size == 0 线性表为空表  size == data.length 线性表满了
    //size 新元素默认尾部添加时要去的角标
    private int size;

    //默认容量
    private static int DEAULT_CAPACITY = 10;

    //默认构造函数:创建一个默认容量为10的线性表
    public ArrayList(){
        data = (E[]) new Object[DEAULT_CAPACITY];
        size = 0;
    }

    //指定默认容量的构造函数:创建一个指定容量的线性表
    public ArrayList(int capacity){
        if(capacity <= 0){
            throw new IllegalArgumentException("capacity must > 0");
        }
        DEAULT_CAPACITY = capacity;
        data = (E[]) new Object[DEAULT_CAPACITY];
        size = 0;
    }

    //指定数组的构造函数:传入一个数组 将该数组封装成为一个线性表
    public ArrayList(E[] arr){
        if(arr == null || arr.length == 0){
            throw new IllegalArgumentException("arr can not be null");
        }
        data = (E[]) new Object[DEAULT_CAPACITY];
        for(int i = 0; i < arr.length; i++){
            add(arr[i]);
        }
    }
    @Override
    public void add(E element) {
        add(size, element);
    }


    @Override
    public void add(int index, E element) {
        if(index < 0 || index > size){
            throw new IllegalArgumentException("add index out of range");
        }
        //判断线性表是否是满状态
        if(size == data.length){
            resize(2 * data.length);
        }
        //向后移动元素
        for(int i = size - 1; i >= index; i--){
            data[i + 1] = data[i];
        }
        //将新元素插入到指定位置
        data[index] =  element;
        size++;

    }

    //扩容/缩容操作 不应该向外界提供
    private void resize(int newLen) {
        E[] newData = (E[]) new Object[newLen];
        for(int i = 0; i < size; i++) {
            newData[i] = data[i];
        }
        data = newData;
    }

    @Override
    public void remove(E element) {//删除指定元素 只删除一次  || 删除所有指定元素(此处只删除一次)
        int index = indexOf(element);
        if(index != -1){
            remove(index);
        }
    }

    @Override
    public E remove(int index) {
        if(index < 0 || index >= size){//可以判空
            throw new IllegalArgumentException("remove index out of range");
        }
        //先保存要删除的值
        E ret = data[index];

        //移动元素
        for(int i = index + 1; i < size; i++){
            data[i-1] = data[i];
        }
        size--;

        //什么时候缩容
        //1.有效元素是容量的1/4
        //2.当前容量不得小于等于默认容量
        if(size == data.length / 4 && data.length > DEAULT_CAPACITY){
            resize(data.length / 2);
        }
        return ret;
    }

    @Override
    public E get(int index) {
        if(index < 0 || index >= size){
            throw new IllegalArgumentException("get index out of range");
        }
        return data[index];
    }

    @Override
    public E set(int index, E element) {
        if(index < 0 || index >= size){
            throw new IllegalArgumentException("set index out of range");
        }
        E ret = data[index];
        data[index] = element;
        return ret;
    }

    @Override
    public int size() {
        return size;
    }
    //额外添加的函数  获取线性表中那个的容量
    private int getCapacity() {
        return data.length;
    }
    @Override
    public int indexOf(E element) {
        /*
        == 比的是啥?
        == 两边是基本数据类型的话 比的是值
            基本数据类型:byte short int long float double boolean char
        == 两边是引用数据类型的话 比的是地址
            数组 字符串 其他的类对象
         */
        for(int i = 0; i < size; i++){
            if(data[i].equals(element)){
                return i;//return结束函数
            }
        }
        return -1;
    }

    @Override
    public boolean contains(E element) {
        return indexOf(element) != -1;
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public void clear() {
        data = (E[]) new Object[DEAULT_CAPACITY];
        size = 0;
    }

    @Override
    public void sort(Comparator<E> c) {
        if(c == null){
            throw new IllegalArgumentException("comparator can not be null");
        }
        //插入排序(优化),从第二个元素开始
        for(int i = 1; i < size; i++){
            E e = data[i];
            int j = 0;
            for(j = i; j > 0 && c.compare(data[j-1],e) > 0; j--){
                data[j] = data[j-1];
            }
            data[j] = e;
        }
    }

    @Override
    public List subList(int fromIndex, int toIndex) {
        if(fromIndex < 0 || toIndex >= size || fromIndex > toIndex){
            throw new IllegalArgumentException("must 0 <= fromIndex <= toIndex <= size - 1");
        }
        ArrayList<E> list = new ArrayList<>();
        for(int i = fromIndex; i <= toIndex; i++){
            list.add(data[i]);
        }   
        return list;
    }


    @Override
    public boolean equals(Object o) {
        //1.判空
        if(o == null){
            return false;
        }
        //2.判自己
        if(this == o){
            return true;
        }
        //3.判类型
        if(o instanceof ArrayList){
            //4.按照自己的逻辑比较
            ArrayList<E> other = (ArrayList<E>) o;
            //5.先比较有效元素的个数
            if(this.size != other.size){
                return false;
            }
            //6.有效元素个数相等的情况下 逐个比较元素
            for(int i = 0; i < size; i++){
                if(!data[i].equals(other.data[i])){
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append('[');
        if (isEmpty()) {
            sb.append(']');
        } else {
            for (int i = 0; i < size; i++) {
                sb.append(data[i]);
                if (i == size - 1) {
                    sb.append(']');
                } else {
                    sb.append(',');
                    sb.append(' ');
                }
            }
        }
        return sb.toString();
    }

    //获取当前这个数据结构/容器的迭代器
    //通过迭代器对象 更方便的挨个去除每一个元素
    //同时 实现了Iterable 可以让当前的数据结构/容器 被foreach循环遍历
    @Override
    public Iterator iterator() {

        return new ArrayListIterator();
    }
    //创建一个属于ArrayList的迭代器
    class ArrayListIterator implements Iterator<E> {//内部类
        private int cur = 0;

        @Override
        public boolean hasNext() { //判断是否有下一个元素
            return cur < size;
        }

        @Override
        public E next() { //如果有下一个元素,则把当前元素返回 并移至到下一个元素
            return data[cur++];
        }
    }

}

测试结果:

package p0.测试;

import p2.线性结构.ArrayList;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Random;

public class TestArrayList {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        System.out.println(list);
        Random random = new Random();
        for (int i = 0; i < 10; i++) {
            list.add(random.nextInt(100));
        }
        System.out.println(list);

        for (int i = 0; i < 10; i++) {
            list.add(0, i);
        }
        System.out.println(list);

        list.sort(new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2 - o1;
            }
        });
        System.out.println(list);
        

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


[]
[4, 18, 17, 83, 54, 90, 28, 8, 94, 24]
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 4, 18, 17, 83, 54, 90, 28, 8, 94, 24]
[94, 90, 83, 54, 28, 24, 18, 17, 9, 8, 8, 7, 6, 5, 4, 4, 3, 2, 1, 0]
94 90 83 54 28 24 18 17 9 8 8 7 6 5 4 4 3 2 1 0

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值