ArrayList source parsing (b)

Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
This link: https://blog.csdn.net/dengyu810/article/details/102731084

Welcome reproduced, reprinted, please indicate the source, thank you.

https://www.cnblogs.com/sx-wuyj/p/11177257.html

Learned own record ArrayList source.

Previous continues, ArrayList source code parsing (a)

  • addll (Collection <? extends E> c): adding to a collection of original collection target.

     //参数需要是Collection的子类
        public boolean addAll(Collection<? extends E> c) {
            //将C集合通过toArray()方法转为数组
            Object[] a = c.toArray();
            //拿到传入数组的长度
            int numNew = a.length;
            //对底层数组进行扩容
            ensureCapacityInternal(size + numNew);  // Increments modCount
            //复制数组
            System.arraycopy(a, 0, elementData, size, numNew);
            //将size更新为size+numNew
            size += numNew;
            //返回boolean
            return numNew != 0;
        }

    ensureCapacityInternal(size + numNew);

    About this method, a blog on which a detailed explanation, you can go and see .
  • add (int index, Collection c <extends E?>): add to the original collection target set specified location

    public boolean addAll(int index, Collection<? extends E> c) {
            //检验index
            rangeCheckForAdd(index);
            //将C集合通过toArray()方法转为数组
            Object[] a = c.toArray();
            //拿到传入数组的长度
            int numNew = a.length;
            //对底层数组进行扩容
            ensureCapacityInternal(size + numNew);  
            //计算需要复制的长度
            int numMoved = size - index;
            //需要复制的长度如果大于0,通过arraycopy方法复制
            if (numMoved > 0)
                System.arraycopy(elementData, index, elementData, index + numNew,
                                 numMoved);
            //将参数数组复制到底层数组index位置.
            System.arraycopy(a, 0, elementData, index, numNew);
            //修改size的值  为size+numNew
            size += numNew;
            //返回boolean
            return numNew != 0;
        }

    In fact addAll () method as long as the understanding of the expansion mechanism, other content is very simple, but this method should be noted that according to the index to insert the time.

    if (numMoved > 0)
        System.arraycopy(elementData, index, elementData, index + numNew,numMoved);
    
    System.arraycopy(a, 0, elementData, index, numNew);

    See the source code, you may wonder why you want to copy it twice the first judge, when in fact there is another layer of meaning:? Determine whether the insertion position in the middle of the underlying array, if you need the element after the inserted position back mobile, which is copied to a new array

    The second copy is the combination of the two numbers is an array, which is the underlying array.

  • get (int index): Gets the element at the specified position

     public E get(int index) {
            rangeCheck(index);
            return elementData(index);
        }

    get method everyone is familiar with the source code is also very simple, perhaps rangeCheck () method is relatively unfamiliar.

     private void rangeCheck(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
        }

    Nothing more, we pass the index can not exceed the maximum size, this is well understood.

  • set (int index, E element): Modify element at the location

    public E set(int index, E element) {
            rangeCheck(index);
    
            E oldValue = elementData(index);
            elementData[index] = element;
            return oldValue;
        }

    In fact, the principles set method is to modify the underlying array element indxe element passed, as the incoming parameters well understood why the use of generics, we can think about our work and study type elements in the collection, a variety , it goes without saying that in this place the benefits of using generics.

    Another point is that the method is set to return to duty, I did not notice before, the return value is the element that was modified.

  • size (): set size

    public int size() {
            return size;
        }
  • Position of an element in a set of first occurrence: indexOf (object o)

     //集合中某个元素第一次出现的位置
        public int indexOf(Object o) {
            //判断传入o是否为null
            if (o == null) {
                //如果为null,循环遍历寻找为null的索引位置
                for (int i = 0; i < size; i++)
                    //因为传入的是一个对象,为null使用==
                    if (elementData[i]==null)
                        //返回出现的位置
                        return i;
            } else {
                //如果不为null,使用equals寻找传输对象位置
                for (int i = 0; i < size; i++)
                    if (o.equals(elementData[i]))
                        //找到返回对象位置
                        return i;
            }
            //找不到对象情况下返回-1
            return -1;
        }

    This method should be noted that, if passed null == time is needed to go looking for.

  • Position the element returns last occurrence: lastIndexOf (Object o)

    public int lastIndexOf(Object o) {
          //判断传入o是否为null
            if (o == null) {
                //如果为null,循环遍历寻找为null的索引位置
                //这里是倒序遍历
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                //如果不为null,使用equals寻找传输对象位置
                //同样是倒序遍历
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }

    In fact, two ways of thinking indeOf () and lastIndexOf () is the same, the difference is a positive-order traversal, a reverse traversal.

  • clone (): Cloning

    public Object clone() {
            try {
                //调用了父类也就是Object的clone.
                ArrayList<?> v = (ArrayList<?>) super.clone();
                //集合V的底层数组复制一个原集合底层数组
                v.elementData = Arrays.copyOf(elementData, size);
                v.modCount = 0;
                //返回V集合
                return v;
            } catch (CloneNotSupportedException e) {
               // this shouldn't happen, since we are Cloneable
                throw new InternalError(e);
            }
        }

    I personally think that this method is not the return value can be ArrayList, can be seen from the source to go back and v is ArrayList. ArrayList but also top-level parent class Object. So this is not too wrong.

    try-catch in the comments mean it can not happen, because we are cloned

  • toArray (): the set of installed for the array type Object

    public Object[] toArray() {
            return Arrays.copyOf(elementData, size);
        }

    In fact, will return to a copy of the underlying array, a low-level calls are still called System.arraycopy () This method does not expand here said.

  • toArray (T [] a): the set of installed for the array of the specified type

     public <T> T[] toArray(T[] a) {
            //如果参数数组的长度小于size,那么直接转换为参数数组类型
            if (a.length < size)
                // Make a new array of a's runtime type, but my contents:
                return (T[]) Arrays.copyOf(elementData, size, a.getClass());
            System.arraycopy(elementData, 0, a, 0, size);
            //如果参数数组长度大于size
            //那么返回去的数组[size]为null
            if (a.length > size)
                a[size] = null;
            return a;
        }

    This difference between the two overloaded methods is that the first returns an array of type Object, the second will return an array of the specified type.

  • remove (int index): delete the element at the location

     public E remove(int index) {
            //校验
            rangeCheck(index);
            modCount++;
            //被删除的元素
            E oldValue = elementData(index);
            //需要被复制的元素个数
            int numMoved = size - index - 1;
            //如果被复制的元素个数大于0,那么就复制一个数组
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            //将底层数组最后一个元素设置为null
            //让GC开始工作
            elementData[--size] = null;
            //返回被删除的元素
            return oldValue;
        }

    If the copied elements Ge prime less than or equal to 0, it means the end of an element is deleted, no need to change the element position.

  • remove (Object o): delete the specified element

     public boolean remove(Object o) {
            //判断需要删除的对象是否为null
            if (o == null) {
                //遍历底层数组,使用==null来寻找
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                //如果不是null,是一个对象
                //遍历底层数组,使用equals来寻找
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            //如果没有找到返回false
            return false;
        }

    Also is overloaded, wherein fastRemove () method and remove () logically consistent, but there is no return value and the private modifier, it is a private method.

      private void fastRemove(int index) {
            modCount++;
            // //需要被复制的元素个数
            int numMoved = size - index - 1;
            //如果被复制的元素个数大于0,那么就复制一个数组
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            //将底层数组最后一个元素设置为null
            //让GC开始工作
            elementData[--size] = null; // clear to let GC do its work
        }
  • clean (): set clear internal elements, to become an empty set

     public void clear() {
            modCount++;
    
            // clear to let GC do its work
            for (int i = 0; i < size; i++)
                elementData[i] = null;
    
            size = 0;
        }

    This should clear it is that loops through the bottom of the array, all of the elements of the underlying array is set to null, and modify the size 0;

Some personal simple to understand. There are no written part of the method. Limited time and space, I write to you first, before continuing updates.

If in the process of reading by. I is limited to bring the misguided hope that big brother can criticism. Common progress

Guess you like

Origin blog.csdn.net/dengyu810/article/details/102731084