每日一类-手写ArrayList-泛型

概述

        上一篇手写ArrayList并不完整,相对重要的contains,indexOf,remove方法都没有,更重要的没有支持泛型。又刚好这些方法都跟泛型存在一定关系,所以本篇就以这个3个方法为基础继续完善MyArrayList。

泛型改造

        首先要做的,先对原先MyArrayList进行泛型改造:1>定义类名时声明泛型  2>使用用泛型替换原先的方法中Object

public class MyArrayList<E> {...}

   

具体做法,很简单,就是将原先Object 类型参数,转换成E即可,比如:

    /**
     * 获取指定索引的数据
     * @param index 索引
     * @return 数据
     */
    public E get(int index) {
        if (index >= size || index < 0){
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
        }
        return (E) elementData[index];
    }

 定位-indexOf

indexOf(element)方法返回指定元素在集合中索引位置(第一个匹配的),如果不存在,则返回-1。具体实现逻辑不能,就是遍历所有元素,跟传入的元素比对,如果一样(相等)返回当前元素的索引即可。这里存在难点,如何判断元素相等?

java中常规比较方式有2种:

1:比较内存地址:   A对象 == B对象

2:比较内容:A对象.equals(B对象)  A变量 == B变量 (基本类型) 

这里注意,如果A对象 没有重写Object对象equals方法,默认比较是内存地址,这里讲的是重写后的对象。

public class Object {   
    public boolean equals(Object obj) {
        return (this == obj);
    }
}

 这里是实现逻辑,如果为null,等值比较,如果不为null,调用比较对象的equals方法。这里要注意啦,如果比较对象不重写Object父类的equals比较的是内存地址。

    /**
     * 返回第一次匹配的元素所在索引位置
     * @param element 要查的元素
     * @return
     */
    public int indexOf(E element){
        for(int i = 0;i < size; i++){
            if(element == null){
                if(elementData[i] == null){
                    return i;
                }
            }else{
                if(element.equals(elementData[i])){
                    return i;
                }
            }
        }
        return -1;
    }

包含-contains

包含,判断指定元素是否在集合中,返回true与false。方法实现逻辑indexOf类似:

    /**
     * 判断指定对象是否存在集合中
     * @param element
     * @return
     */
    public boolean contains(E element) {
        return indexOf(element) >= 0;
    }

删除-remove

remove(index) 跟 remove(element) 区别:都是删除元素,前一个根据索引删除,只要对应索引有值便可以删除,后一个根据元素删除,只要删除原则在集合中便可以删除。

    /**
     * 判断指定对象是否存在集合中
     * @param element
     * @return
     */
    public boolean remove(E element) {
        int i = this.indexOf(element);
        if(i != -1){
            remove(i);
            return true;
        }
        return false;
    }

到这,MyArrayList的基本方法就结束啦,上一份完整代码,后续抽空把迭代器加上就差不多,期待。

public class MyArrayList<E> {

    private int size;  //存放数据大小
    private Object[] elementData;  //存放数据数组
    //默认长度
    private static final int DEFAULT_CAPACITY = 10;
    //模仿ArrayList初始化 2个空数组,执行add时才进行扩容
    private static final Object[] EMPTY_ELEMENTDATA = {};
    //为什么弄2个空数组,官方给出解释:
    // We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate
    //when first element is added.
    //翻译过来就是:我想知道它啥时候塞值进去
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};

    public MyArrayList(){
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

    public MyArrayList(int initialCapacity){
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                    initialCapacity);
        }
    }
    public MyArrayList(MyArrayList list){
        elementData = list.toArray();
        if ((size = elementData.length) == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        }
    }
    public Object[] toArray() {
        //借用工具类啦
        return Arrays.copyOf(elementData, size);
    }

    /**
     * 往数组中添加元素(默认添加到最后)
     * @param element 元素
     * @return 添加成功返回true, 不成功返回false
     */
    public boolean add(E element) {
        this.add(size, element);
        return true;
    }
    //拓展方法
    private void grow() {
        int oldCapacity = elementData.length; //新长度
        int newCapacity;
        if(oldCapacity == 0){
            newCapacity = DEFAULT_CAPACITY;
        }else{
            //扩展增幅是 1.5倍
            newCapacity = oldCapacity + (oldCapacity >> 1);
        }
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    /**
     * 往数组指定位置添加元素(默认添加到最后)
     * @param index 索引
     * @param element 元素
     * @return 添加成功返回true, 不成功返回false
     */
    public boolean add(int index, E element) {
        //检查索引是否正确
        this.rangeCheck(index);
        if(size == elementData.length){
            this.grow();
        }
        System.arraycopy(elementData, index, elementData, index + 1, size - index);
        elementData[index] = element;
        size++;
        return true;
    }
    //检查索引是否正确
    private void rangeCheck(int index) {
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
    }
    /**
     * 根据指定索引删除数据
     * @param index 索引
     * @return 被删除的数据
     */
    public E remove(int index){
        if (index >= size || index < 0){
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
        }
        Object old  = elementData[index];
        if(size - 1 > index){
            System.arraycopy(elementData, index + 1, elementData, index, size -1 - index);
        }
        elementData[size-1] = null;
        size --;
        return (E) old;
    }
    /**
     * 清空集合元素
     */
    public void clear() {
        for (int i = 0; i < size; i++){
            elementData[i] = null;
        }
        size = 0;
    }
    /**
     * 修改指定位置元素数据
     * @param index 索引
     * @param element 元素
     * @return 返回被改动的数据
     */
    public E set(int index, E element) {
        if (index >= size || index < 0){
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
        }
        Object oldValue = elementData[index];
        elementData[index] = element;
        return (E) oldValue;
    }
    /**
     * 获取指定索引的数据
     * @param index 索引
     * @return 数据
     */
    public E get(int index) {
        if (index >= size || index < 0){
            throw new IndexOutOfBoundsException("Index: "+index+", Size: "+size);
        }
        return (E) elementData[index];
    }
    /**
     * 返回第一次匹配的元素所在索引位置
     * @param element 要查的元素
     * @return
     */
    public int indexOf(E element){
        for(int i = 0;i < size; i++){
            if(element == null){
                if(elementData[i] == null){
                    return i;
                }
            }else{
                if(element.equals(elementData[i])){
                    return i;
                }
            }
        }
        return -1;
    }

    /**
     * 判断指定对象是否存在集合中
     * @param element
     * @return
     */
    public boolean contains(E element) {
        return indexOf(element) >= 0;
    }

    /**
     * 判断指定对象是否存在集合中
     * @param element
     * @return
     */
    public boolean remove(E element) {
        int i = this.indexOf(element);
        if(i != -1){
            remove(i);
            return true;
        }
        return false;
    }

    @Override
    public String toString() {
        return "MyArrayList{" +
                "size=" + size +
                ", elementData=" + Arrays.toString(elementData) +
                '}';
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪飞yes

我对钱没兴趣~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值