美文网首页基要稳
【Java集合】ArrayList

【Java集合】ArrayList

作者: Guxxxd | 来源:发表于2021-09-23 10:00 被阅读0次

    继承结构

        public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    

    写在前面的一些方法说明

    • Arrays.copyOf(Object[] original, int newLength),往往一段代码胜过千言万语

    • 移位 >><<

    int a = 8;  // 二进制:··· 0000 1000
    a = a >> 1;  // 二进制:··· 0000 0100
    System.out.println(a)    // 4
    a = a << 2;  // 二进制:··· 0001 0000
    System.out.println(a)    // 16
    
    • System.arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

    • private void grow(int minCapacity)扩容

        private void grow(int minCapacity) {
            // 当前数组的容量
            int oldCapacity = elementData.length;
            // 新容量 = 老容量 + 老容量/2
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            // 如果新容量小于需要申请的容量
            if (newCapacity - minCapacity < 0)
                // 新容量=需要申请的容量
                newCapacity = minCapacity;
            // 如果新容量大于MAX_ARRAY_SIZE(= Integer.MAX_VALUE - 8)
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                // 新容量=计算出的最大容量
                newCapacity = hugeCapacity(minCapacity);
            // 数组扩容到新容量
            elementData = Arrays.copyOf(elementData, newCapacity);
          }
    
         private static int hugeCapacity(int minCapacity) {
            if (minCapacity < 0) // 需要申请的容量小于0 抛异常
                throw new OutOfMemoryError();
            // 需要申请的容量大于最大容量?是->返回int最大值,否->返回int最大值-8
            return (minCapacity > MAX_ARRAY_SIZE) ?
                Integer.MAX_VALUE :
                MAX_ARRAY_SIZE;
          }
    
    • private void ensureCapacityInternal(int minCapacity),如果使用new ArrayList(),当添加第一个元素时,其实容器内已经申请了length=10的容量,添加的元素如果<10,就造成了资源的浪费。
        private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    
        private static final int DEFAULT_CAPACITY = 10;
    
         public ArrayList() {
             this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
         }
    
         private void ensureCapacityInternal(int minCapacity) {
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                // 取最大值作为需要申请的容量
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }
    
            ensureExplicitCapacity(minCapacity);
         }
    
          private void ensureExplicitCapacity(int minCapacity) {
              modCount++;
            // 如果申请的容量大于目前容器的容量,去扩容
            if (minCapacity - elementData.length > 0)
                grow(minCapacity);
          }
    

    一、增

    • public boolean add(E e)
        public boolean add(E e) {
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            elementData[size++] = e;
            return true;
         }
    
    • public void add(int index, E element)
        public void add(int index, E element) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
            ensureCapacityInternal(size + 1);  // Increments modCount!!
            // 把index位置后面的元素全部后移一位
            System.arraycopy(elementData, index, elementData, index + 1,size - index);
            // index位置赋值新元素
            elementData[index] = element;
            size++;
         }
    
    • public boolean addAll(Collection<? extends E> c)
        public boolean addAll(Collection<? extends E> c) {
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
            return numNew != 0;
         }
    
    • public boolean addAll(int index, Collection<? extends E> c)
        public boolean addAll(int index, Collection<? extends E> c) {
            if (index > size || index < 0)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
            // a=[1,2,3,4]
            Object[] a = c.toArray();
            int numNew = a.length;
            ensureCapacityInternal(size + numNew);  // Increments modCount
    
            int numMoved = size - index;
            if (numMoved > 0)
                // 匀出位置
                // index = 1
                // old element = [5,6,7,null,null,null,null]
                // new element = [5,6,7,null,null,6,7]
                System.arraycopy(elementData, index, elementData, index + numNew,
                                 numMoved);
            // 塞进去 new element = [5,1,2,3,4,6,7]
            System.arraycopy(a, 0, elementData, index, numNew);
            size += numNew;
            return numNew != 0;
         }
    

    二、删

    • public E remove(int index),return 移除的那个元素
        public E remove(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
            modCount++;
            E oldValue = (E) elementData[index];
    
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            elementData[--size] = null; // clear to let GC do its work
    
            return oldValue;
          }
    
    • public boolean remove(Object o)
         public boolean remove(Object o) {
            if (o == null) {
                for (int index = 0; index < size; index++)
                    if (elementData[index] == null) {
                        fastRemove(index);
                        return true;
                    }
            } else {
                for (int index = 0; index < size; index++)
                    if (o.equals(elementData[index])) {
                        fastRemove(index);
                        return true;
                    }
            }
            return false;
        }
    
        private void fastRemove(int index) {
            modCount++;
            int numMoved = size - index - 1;
            if (numMoved > 0)
                System.arraycopy(elementData, index+1, elementData, index,
                                 numMoved);
            elementData[--size] = null; // clear to let GC do its work
         }
    
    • public boolean removeAll(Collection<?> c) 删除c中相同的元素public boolean retainAll(Collection<?> c) 保留c中相同的元素,相当于取交集
        public boolean removeAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, false);
         }
    
         public boolean retainAll(Collection<?> c) {
            Objects.requireNonNull(c);
            return batchRemove(c, true);
         }
    
        /**
         * @param complement  true 保留相同元素  false 保留不同元素
         */
        private boolean batchRemove(Collection<?> c, boolean complement) {
            final Object[] elementData = this.elementData;
            int r = 0, w = 0;
            boolean modified = false;
            try {
                for (; r < size; r++)
                    if (c.contains(elementData[r]) == complement)
                        elementData[w++] = elementData[r];
            } finally {
                // Preserve behavioral compatibility with AbstractCollection,
                // even if c.contains() throws.
                if (r != size) {
                    System.arraycopy(elementData, r,elementData, w,size - r);
                    w += size - r;
                }
                if (w != size) {
                    // clear to let GC do its work
                    for (int i = w; i < size; i++)
                        elementData[i] = null;
                    modCount += size - w;
                    size = w;
                    modified = true;
                }
            }
            return modified;
        }
    

    三、改

    • public E set(int index, E element)
        public E set(int index, E element) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
            E oldValue = (E) elementData[index];
            elementData[index] = element;
            return oldValue;
         }
    
    • public void replaceAll(UnaryOperator<E> operator) 根据定义的规则进行单个元素的转换
        public void replaceAll(UnaryOperator<E> operator) {
            Objects.requireNonNull(operator);
            final int expectedModCount = modCount;
            final int size = this.size;
            for (int i=0; modCount == expectedModCount && i < size; i++) {
                elementData[i] = operator.apply((E) elementData[i]);
            }
            if (modCount != expectedModCount) {
                throw new ConcurrentModificationException();
            }
            modCount++;
        }
    
        // 例
        public static void main(String[] args) {
            ArraysList<String> list = new ArraysList<>();
            list.add("1");
            list.add("2");
            list.add("3");
    
            list.replaceAll(new UnaryOperator<String>() {
                @Override
                public String apply(String s) {
                    return s.equals("1") ? "2" : s;
                }
            });
    
            for (String o : list) {
                System.out.print(o);
                System.out.print(",");
            }
          // 输出:[2,2,3]
        }
    }
    

    四、查

    • public int indexOf(Object o) 正序遍历数组比较元素,返回索引
        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;
        }
    
    • public boolean contains(Object o)
        public boolean contains(Object o) {
            return indexOf(o) >= 0;
        }
    
    • public int lastIndexOf(Object o)倒序遍历数组比较元素,返回索引
        public int lastIndexOf(Object o) {
            if (o == null) {
                for (int i = size-1; i >= 0; i--)
                    if (elementData[i]==null)
                        return i;
            } else {
                for (int i = size-1; i >= 0; i--)
                    if (o.equals(elementData[i]))
                        return i;
            }
            return -1;
        }
    
    • public E get(int index)索引取数组元素
        public E get(int index) {
            if (index >= size)
                throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    
            return (E) elementData[index];
        }
    

    相关文章

      网友评论

        本文标题:【Java集合】ArrayList

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