【ArrayList】集合

一、ArrayList的父类

        Arraylist是集合的一部分,它的根本父类是Collection,所以在说Arraylist之前我们浅说一下集合,集合和数组有很大的区别

数组集合
长度定长,不能改变不定长
存储的数据类型只能存一种, 能存储基本类型和引用类型可以存多种数据类型; 只能存储引用类型
属性和方法只有一个属性length,没有方法提供了属性,以及方法
插入顺序和遍历顺序有顺序,插入和遍历顺序一致有的集合有序 有的集合无序 有的集合会排序
允许重复元素允许重复有的集合允许重复 有的集合不允许重复

集合的体系结构图

        1、Collection

Collection是集合层级的根接口

里面定义了后续子类中需要使用的一些共有方法

但是因为是接口,无法演示,但是它有两个常用的子接口

  • List

  • Set

        2、List

List集合,是Collection的子接口

List集合,保证有序,且允许重复元素的集合

List集合,能通过下标对数据进行精准控制(通过下标对数据进行增删改查)

List集合是接口,无法直接使用,但是它有两个常用的实现类

  • ArrayList

  • LinkedList

二、ArrayList

        2.1 介绍

  • ArrayList是List实现类,即ArrayList也是允许存储重复元素,且保证顺序(插入和遍历顺序一致)

  • ArrayList也可以通过下标来操作数组

  • ArrayList底层是数组

  • ArrayList是不保证线程安全的,即不同步

        2.2 演示API(共用方法)

private static void show1() {
        ArrayList list = new ArrayList();// 创建了一个集合对象
​
                                // 向集合中添加1个元素(只能存储对象)
        list.add(5);
        list.add(2);
        list.add(2);
        list.add(3);
        list.add(3);
        list.add(1);
        list.add(4);
                               // 存储的元素有序,且允许重复
        System.out.println(list );
​
                               // addAll(Collection c),将集合中的所有元素添加到该集合中
        ArrayList list2 = new ArrayList();
        list2.add(11);
        list2.add(22);
        list2.add(33);
​
        ArrayList list3 = new ArrayList();
        list3.add(44);
        list3.add(55);
        list3.add(66);
        System.out.println(list3 );
​
        list3.addAll(list2);
        System.out.println(list3 );
​
                                 // 判断是否包含该元素
        System.out.println(list3.contains(1));
        System.out.println(list3.containsAll(list2));
​
                                 // 移除元素
        Integer i = 11;
        list3.remove(i);
        System.out.println(list3 );
                                                                                                       

        ArrayList list4 = new ArrayList();
        list4.add(33);
        list4.add(55);
​
                                // list3.removeAll(list4); // 指定移除多个
        list3.retainAll(list4);// 指定保留多个
        System.out.println(list3 );
​
                                // 集合大小(元素个数)
        System.out.println(list3.size( ));
​
                                // 是否为空
        System.out.println(list3.isEmpty( ));
​
                                // 清空集合
        list3.clear();
                                // 是否为空
        System.out.println(list3.isEmpty( ));
    }

        2.3 演示API(关于下标操作)

ArrayList是基于数组实现,是能通过下标精准操作数据的

private static void show2() {
    ArrayList list = new ArrayList( );
    list.add(1);
    list.add(2);
    list.add(3);
    list.add(4);
    System.out.println("list = " + list);
​
                    // add(int index,Object o)
                    // 在指定下标插入数据
    list.add(2,5);
    System.out.println("list = " + list);
​
                    // set(int index,Object o)
                    // 修改/设置指定下标的值
    list.set(2,50);
    System.out.println("list = " + list);
​
                    // Object get(int index)
    Object o = list.get(2);
    System.out.println("o = " + o);
​
                    // remove(int index)或者remove(object o)
    list.remove(2);
    System.out.println("list = " + list);
​
                    // subList(x,y)截取集合中的元素,左闭右开
    List l2 = list.subList(1, 3);
    System.out.println("l2 = " + l2);
}

三、集合迭代

迭代,即遍历

Collection顶层父接口中提供了一个Iterator接口可以运行迭代集合

 public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>( );
        list.add(5);
        list.add(3);
        list.add(2);
        list.add(1);
        list.add(4);
​
        // 获得迭代器
        Iterator<Integer> iterator = list.iterator( );
        while (iterator.hasNext()){// 判断有无下一个
            Integer i = iterator.next( );// 取出下个
            System.out.println(i );
        }
​
        // 一般上面的迭代器,可以简化成foreach,又叫增强for循环
        // :左边是遍历得到的结果变量,右边是要遍历的集合或者是数组
        for(Integer i : list) {
            System.out.println(i );
        }
​
        int[] arr = {1,2,3,4,5};
        for (int i:arr){
            System.out.println(i);
        }
    }

四、ArrayList底层原理

ArrayList是有序,允许重复 ---> 是因为,底层是使用数组实现的


  • 当new ArrayList时,默认创建了长度为0的数组

  • 当第一次add的时候,创建了一个容量为10的数组

  • 当添加到第11位时,要扩容,成原来的1.5倍

public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // 最初长度为0
        elementData[size++] = e;
        return true;
    }




private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {      //DEFAULTCAPACITY_EMPTY_ELEMENTDATA默认为空
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }





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

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);                            //如果最小容量减去原来的对象长度大于零,说明容量已经不够了,就需要进行扩容
    }





    /**
     * The maximum size of array to allocate.
     * Some VMs reserve some header words in an array.
     * Attempts to allocate larger arrays may result in
     * OutOfMemoryError: Requested array size exceeds VM limit
     */
    private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;




    /**
     * Increases the capacity to ensure that it can hold at least the
     * number of elements specified by the minimum capacity argument.
     *
     * @param minCapacity the desired minimum capacity
     */
    private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);        //扩容到原来的1.5倍
        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);
    }

解释如下(来自通义灵码)

这些函数是Java集合框架中ArrayList类的内部方法,用于确保ArrayList具有足够的容量来添加新元素。
ensureCapacityInternal(int minCapacity) 方法:
检查当前ArrayList的容量是否足够,如果不够则调用 ensureExplicitCapacity(minCapacity) 方法来确保容量足够。
ensureExplicitCapacity(int minCapacity) 方法:
增加modCount,用于记录ArrayList的结构修改次数。
如果所需的最小容量大于当前数组长度,则调用 grow(minCapacity) 方法来增加数组容量。
grow(int minCapacity) 方法:
计算新的容量大小,通常是当前容量的1.5倍。
如果新的容量小于所需的最小容量,则将新的容量设置为所需的最小容量。
如果新的容量超过最大数组大小,则调用 hugeCapacity(minCapacity) 方法来处理。
最后,使用Arrays.copyOf方法创建一个新的数组,容量为新的容量,并将当前元素数据复制到新数组中。
这些方法的目的是为了确保ArrayList在添加新元素时能够有足够的空间,如果空间不足,则会增加容量,以避免频繁地重新分配内存。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值