ArrayList

ArrayList

说明

ArrayList是List的一个实现类,底层是数组,查询快,增删慢,线程不安全

实践

class Student {
    String name;
    Integer age;

    public Student() {
    }

    public Student(String name, Integer age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public Integer getAge() {
        return age;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        Student student = (Student) o;
        return Objects.equals(name, student.name) && Objects.equals(age, student.age);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }
}
package com.qianfeng.collection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.ListIterator;

/**
 * 功能描述
 *
 * @since 2022-05-07
 */
public class ArrayListDemo {
    public static void main(String[] args) {
        ArrayList<Object> arrayList = new ArrayList<>();

        Student s1 = new Student("张三", 10);
        Student s2 = new Student("李四", 11);
        Student s3 = new Student("王五", 12);

        // 添加元素
        arrayList.add(s1);
        arrayList.add(s2);
        arrayList.add(s3);
        arrayList.add(s3);
        System.out.println(arrayList);

        // 删除元素
        arrayList.remove(new Student("李四", 11));
        System.out.println(arrayList);

        //遍历
        System.out.println("==============迭代器遍历================");
        Iterator it = arrayList.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        System.out.println("==============迭代器遍历================");
        ListIterator lit = arrayList.listIterator();
        while (lit.hasNext()) {
            System.out.println(lit.next());
        }

        System.out.println("==============迭代器遍历逆序================");
        while (lit.hasPrevious()) {
            System.out.println(lit.previous());
        }

        //判断
        System.out.println(arrayList.isEmpty());
        System.out.println(arrayList.contains(new Student("王五", 12)));
        //定位
        System.out.println(arrayList.indexOf(new Student("王五", 12)));
    }
}

源码分析

带着疑问看源码
1.ArrayList底层是数组,数组的大小在初始化的时候确定,初始的尺寸如何确定?扩容如何实现?缩容呢?
数组的大小即容量

容量:
当ArrayList中没有数据时,容量为0,添加一个数据后,容量为10,元素数量超出容量后进行扩容,每次扩容为原来的1.5倍

初始参数

DEFAULT_CAPACITY = 10; //初始容量是10
transient Object[] elementData; //数据最终存储在该数组内 
private int size; // ArrayList包含元素的个数

arrayList.add()源码分析

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

private void ensureCapacityInternal(int minCapacity) {
    ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}

private static int calculateCapacity(Object[] elementData, int minCapacity) {
    if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
        return Math.max(DEFAULT_CAPACITY, minCapacity);
    }
    return minCapacity;
}

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    // overflow-conscious code
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
}

// 扩容的核心代码
private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    // 扩容每次扩原来容量的1.5倍
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    // 首次扩容时扩容到10
    if (newCapacity - minCapacity < 0)
        newCapacity = minCapacity;
    if (newCapacity - MAX_ARRAY_SIZE > 0)
        newCapacity = hugeCapacity(minCapacity);
    // minCapacity is usually close to size, so this is a win:
    // 将原数组复制到新的长度的数组中
    elementData = Arrays.copyOf(elementData, newCapacity);
}

remove方法源码分析
看完源码可以得出 ArrayList没有自动缩容的机制,想要缩容需要手动调用trimToSize方法

public E remove(int index) {
    // index范围检查
    rangeCheck(index);

    modCount++;
    E oldValue = elementData(index);

    int numMoved = size - index - 1;
    // 调用本地方法实现数组的拷贝,将index+1及后面的元素移动到index处
    if (numMoved > 0)
        System.arraycopy(elementData, index+1, elementData, index,
                            numMoved);
    elementData[--size] = null; // clear to let GC do its work

    return oldValue;
}

trimToSize 手动缩容即直接缩容至当前集合包含的元素个数

public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = (size == 0)
            ? EMPTY_ELEMENTDATA
            : Arrays.copyOf(elementData, size);
    }
}



posted @ 2022-05-07 10:57  Oh,mydream!  阅读(45)  评论(0编辑  收藏  举报