手写一个Arraylist分析java数组和List区别

疑问:数组和list有很多相似之处,二者有何区别
java数组的定义:
1.数组的数据在计算机存贮器占用一片连续的存储空间,所以它的索引速度是非常的快,而且赋值与修改元素也很简单。
2.通过下标和和标识符访问每一个数据元素。
3.数组大小是在初始化的时候固定的,大小不可改变。
4.数组通过length查看数组大小,如果想知道实际保存的元素数量得遍历判断是否为null。
java 的List继承自Collection,用的比较多的是它的实现类ArrayList:
1.ArrayList对象的数据结构有一个数组,它的属性数组用来保存数据。
2.ArrayList的size大小不固定,每次add新的元素后size加一。
3.ArrayList就是基于数组创建的容器类。
4.ArrayList通过调用size()方法查看实际保存得元素个数。
手写一个MyArraylist实例:

手写的MyArraylist模仿实现了ArrayList常用的add()、remove()和get()方法,通过测试可以看出ArrayList实际也是用一个Object[]保存数据,然后把取一个元素和增加一个元素等过程用一个方法封装起来,第一次add元素的时候初始化一个数据大小为10,当增加的元素超过数组大小的时候就得重新初始化一个更大的数据然后把旧数组里面的数据copy过去。如果想更深入了解,应该去看源码。

思考:当需要往集合添加很多元素的时候,而且大概知道元素有多少,初始化ArrayList的时候是不是指定数组大小从而减少扩容步骤达到减少cpu和时间消耗
手写ArrayList测试
package com.xy.initializer;

import java.util.*;

/**@desc:只是实现了size() 、add(E e)、remove(Object o),方便直观表达.
 * 为了不报错MyAbstractList<E>类实现接口其他方法(接口的实现类必须实现接口的所有方法)
 * @Date ........
 * @author xy
 */
public class MyArrayList<E> extends MyAbstractList<E> {
    //jdk中的关键字是transient,这里为了方便理解用private
    private Object[] elementData;
    //第一次调用add方法初始化数组的大小
    private static final int DEFAULT_CAPACITY = 10;
    //记录数组中存了多少元素
    private int size;

    public MyArrayList(){
        this.elementData = new Object[]{};
    }

    @Override
    public int size() {
        return this.size;
    }
    /**
     *向集合MyArrayList中增加一个元素
     * @param e
     * */
    @Override
    public boolean add(E e) {
        if(elementData.length==0){
            elementData = Arrays.copyOf(elementData, DEFAULT_CAPACITY);
        }
        //如果新增的元素加上之前存的元素大于数组的长度就要扩容,扩容的大小是数组原长度+数组原长度二进制右移一位。
        // 例如10二进制为1010右移一位变成101,再换成十进制也就是5
        if(size+1>elementData.length){
            int oldCapacity = elementData.length;
            int newCapacity = oldCapacity +(oldCapacity >> 1);
            //Arrays.copyOf为jdk类文件方法,返回一个新数组,长度是参数newCapacity的大小
            elementData = Arrays.copyOf(elementData, newCapacity);
        }
        elementData[size] = e;
        size++;
        return true;
    }
    /**
     *删除集合MyArrayList中指定索引下一个元素
     * @param index
     * */
    @Override
    public E remove(int index) {
        if (index >= size){
            throw new IndexOutOfBoundsException("索引下标超过size的大小");
        }
        E oldValue = get(index);
        int numMoved = size - index - 1;
        if (numMoved > 0)
            //jdk底层方法,这里达到的效果是删除了指定下标的值,想了解删除原理可以百度了解下
            System.arraycopy(elementData, index+1, elementData, index,
                    numMoved);
        elementData[--size] = null;
        return oldValue;
    }
    /**
     *得到集合MyArrayList中指定索引下一个元素
     * @param index
     * */
    public E get(int index) {
        if (index >= size){
            throw new IndexOutOfBoundsException("索引下标超过size的大小");
        }
        return (E) elementData[index];
    }

    public static void main(String[] args) {
        List<String> strs = new MyArrayList<String>();
        strs.add("你好!");
        strs.add("我很好!");
        System.out.println("strs里面的元素个数:"+strs.size()+"\t strs的第一个元素是:"+strs.get(0)+"\t strs的第二个元素是:"+strs.get(1));
        strs.remove(0);
        System.out.println("strs里面的元素个数:"+strs.size()+"\t 删除一个元素后strs的第一个元素是:"+strs.get(0));
        String msg = strs.get(1);
        System.out.println("strs里面的元素个数:"+strs.get(1));
    }
}

MyAbstractList类源码(MyAbstractList类是为了将List不需要分析的方法实现,这样MyArrayList只实现List接口三个方法也不会报错):
package com.xy.initializer;

import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

public class MyAbstractList<E> implements List<E> {
    @Override
    public int size() {
        return 0;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean contains(Object o) {
        return false;
    }

    @Override
    public Iterator<E> iterator() {
        return null;
    }

    @Override
    public Object[] toArray() {
        return new Object[0];
    }

    @Override
    public <T> T[] toArray(T[] a) {
        return null;
    }

    @Override
    public boolean add(E e) {
        return false;
    }

    @Override
    public boolean remove(Object o) {
        return false;
    }

    @Override
    public boolean containsAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean addAll(Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean addAll(int index, Collection<? extends E> c) {
        return false;
    }

    @Override
    public boolean removeAll(Collection<?> c) {
        return false;
    }

    @Override
    public boolean retainAll(Collection<?> c) {
        return false;
    }

    @Override
    public void clear() {

    }

    @Override
    public E get(int index) {
        return null;
    }

    @Override
    public E set(int index, E element) {
        return null;
    }

    @Override
    public void add(int index, E element) {

    }

    @Override
    public E remove(int index) {
        return null;
    }

    @Override
    public int indexOf(Object o) {
        return 0;
    }

    @Override
    public int lastIndexOf(Object o) {
        return 0;
    }

    @Override
    public ListIterator<E> listIterator() {
        return null;
    }

    @Override
    public ListIterator<E> listIterator(int index) {
        return null;
    }

    @Override
    public List<E> subList(int fromIndex, int toIndex) {
        return null;
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容