美文网首页
重新认识ArrayList

重新认识ArrayList

作者: 赵呆一 | 来源:发表于2020-07-03 11:57 被阅读0次

    前言

    看了很多博客对于arraylist也只是停留在add remove上 只知道arraylist是个数组 里面装的是对象 知道有一天发现 在循环remove的时候删除的数据错误的 (二次循环过滤重复数据)后来用iterator来解决的 使用的很片面。

    主题

    首先ArrayList是非线程安全的 动态数组

    1.线程不安全的原因
    各类面试题一直说ArrayList线程不安全 但为什么线程不安全懵懵懂懂

    QQ截图20200703105622.png

    如果两个线程同时add的时候 因为是数组 假如原来数组的长度为8 第一个线程增加一个为9 第二个线程增加一个也为9 同一时间增加了两个数据 会导致数组越界的情况 所以线程不安全

    2. ArrayList的扩容策略

    QQ截图20200703110102.png QQ截图20200703111019.png QQ截图20200703111211.png

    假如容量不够了 旧的容量加上旧的容量移位1
    如果比最小的还要小 就置换
    如果比最大的还要大 直接给一个int类型最大的数

    这里有一个默认的属性DEFAULT_CAPACITY 也就是说 当第一次扩容时判断是空 首先默认为0 第一次扩容时候 有可能扩容的值为10 但如果需要的数量更大时则申请的是更大的容量

    QQ截图20200703135402.png

    ArrayList的继承结构

    QQ截图20200703102713.png
    1.AbstractList

    抽象的list类 继承了AbstractCollection 实现了List接口 把各个接口里的内容重新抽取起来 abstract 重新再封装 (装饰模式)提供了add clear addAll等方法

    QQ截图20200703111556.png

    这里倒是有个疑问 为什么AbstractList已经实现了List接口了 为什么ArrayList也要重新再实现一遍这个接口目的是为了什么?

    1.虽然从语义上是冗余的,但设计是合理的 ArrayList作为一个对象首先符合List接口定义,基于接口开闭原则,将List的一些固定行为进行抽象使得ArrayList必须实现List中的所有方法

    2. RandomAccess Cloneable java.io.Serializable

    这两个接口是空接口实现的意义是什么呢?

    RandomAccess在Collections里有大量的 instanceof这种
    判断是否实现了这个接口 做一个区分
    加快随机访问的速度
    这里有人又要问 加快随机访问速度有啥用 为啥ArrayList有 LinkedList没有勒

    int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
        int low = 0;
        int high = list.size()-1;
    
        while (low <= high) {
            int mid = (low + high) >>> 1;
            Comparable<? super T> midVal = list.get(mid);
            int cmp = midVal.compareTo(key);
    
            if (cmp < 0)
                low = mid + 1;
            else if (cmp > 0)
                high = mid - 1;
            else
                return mid; // key found
        }
        return -(low + 1);  // key not found
    }
    

    如果是数组形式就while循环来查找 如果是其他形式就用迭代器的方式进行查找

    Cloneable 作用 clone的时候需要这个接口

    java.io.Serializable 支持序列化 可以进行intent传输 或者进程间的数据传输

    ArrayList 初始化 add addAll remove removeAll 操作

    初始化

    QQ截图20200703114740.png

    这里默认是一个空数组

    QQ截图20200703114436.png

    添加数据 扩容

    QQ截图20200703114919.png

    之前用两层for循环去remove数据的时候总是出现各种各样的问题
    因为是数组 如果正向删除的话会出现问题 或者用迭代删除

    ArrayList的contains比较

       /**
         * Returns <tt>true</tt> if this list contains the specified element.
         * More formally, returns <tt>true</tt> if and only if this list contains
         * at least one element <tt>e</tt> such that
         * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
         *
         * @param o element whose presence in this list is to be tested
         * @return <tt>true</tt> if this list contains the specified element
         */
        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    
        /**
         * Returns the index of the first occurrence of the specified element
         * in this list, or -1 if this list does not contain the element.
         * More formally, returns the lowest index <tt>i</tt> such that
         * <tt>(o==null&nbsp;?&nbsp;get(i)==null&nbsp;:&nbsp;o.equals(get(i)))</tt>,
         * or -1 if there is no such index.
         */
        public int indexOf(Object o) {
            if (o == null) {
                for (int i = 0; i < size; i++)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    

    ArrayList 对象比较
    如果对象不为空则进入equals比较方法
    如果对象为空的话 而且ArrayList里的每一项内容不为空的话 返回true

    最后

    希望先做一个初步总结,后续有时间在重新锊一遍代码

    相关文章

      网友评论

          本文标题:重新认识ArrayList

          本文链接:https://www.haomeiwen.com/subject/eawjqktx.html