扩充机制

package com.zmz.collection;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @author 张明泽
 * Create by 2022/5/16 12:24
 */
public class ArrayListDemo {
    /**
     * ArrayList 初始化长度为 10
     * 调用有参构造传多少是多少
     * 扩充机制:当前长度进行移位运算 + 当前长度  (10,15,22,33,49,73)
     * 二次添加时,若传入的长度大于扩充的长度 (11),结果为: Math.max(扩充的长度,11)
     * 二次添加时,只会扩充一次,不会扩到大于传入的长度,案例见下面的情况
     *
     * size()方法只能查看数组的个数,需要利用反射机制去查看数组容量
     */
    public static void main(String[] args) throws Exception {
        /**
         * 第一种情况
         */
        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.addAll(Arrays.asList(1,2,3));
        System.out.println("数组的长度" + getArrayListLength(arrayList1)); // 10
        /**
         * 第二种情况
         */
        ArrayList<Integer> arrayList2 = new ArrayList<>();
        // 小于10 长度就扩充为10  大于10 传多少是多少 (本身的容量为10,不会二次扩容)
        arrayList2.addAll(Arrays.asList(1,2,3,4,5,6,7,8,9,10,11,12,13));
        System.out.println("数组的长度" + getArrayListLength(arrayList2)); // 13
        /**
         * 第三种情况
         */
        ArrayList<Integer> arrayList3 = new ArrayList<>();
        arrayList3.addAll(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
        // 添加之前先扩容 5 + 10 > 13
        arrayList3.addAll(Arrays.asList(11,12,13));
        System.out.println("数组的长度" + getArrayListLength(arrayList3)); // 15
        /**
         * 第四种情况
         */
        ArrayList<Integer> arrayList4 = new ArrayList<>();
        arrayList4.addAll(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
        // 添加之前先扩容 5 + 10 < 16
        arrayList4.addAll(Arrays.asList(11,12,13,14,15,16));
        System.out.println("数组的长度" + getArrayListLength(arrayList4)); // 16
    }
    // 查看ArrayList集合容量方法 -- 反射
    public static int getArrayListLength(List list) throws Exception{
        //获取Class对象
        Class c = Class.forName("java.util.ArrayList");
        //映射Class对象所表示类的属性
        Field field = c.getDeclaredField("elementData");
        //设置访问表示为true
        field.setAccessible(true);
        //返回指定对象上此 Field 表示的字段的值
        Object[] object = (Object[])field.get(list);
        return object.length;
    }
}

迭代器

fail-fast 一旦发现遍历的同时其他人来修改,则立刻抛异常
fail-safe 发现遍历的同时其他人来修改,应当能有对应策略,例如牺牲一致性来让整个遍历运行完成

package com.zmz.collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author 张明泽
 * Create by 2022/5/16 14:55
 */
public class IteratorDemo {
    /**
     * fail-fast 一旦发现遍历的同时其他人来修改,则立刻抛异常
     * fail-safe 发现遍历的同时其他人来修改,应当能有对应策略,例如牺牲一致性来让整个遍历运行完成
     */
    public static void main(String[] args) {
        failFast();
    }
    public static void failFast() {
        ArrayList<Student> arrayList = new ArrayList<>();
        /**
         * add()方法,原数组上继续添加
         */
        arrayList.add(new Student("A"));
        arrayList.add(new Student("B"));
        arrayList.add(new Student("C"));
        arrayList.add(new Student("D"));
        /**
         * 加入断点,student.name.equals("C") 然后在加入一个"E",继续执行时会抛出异常
         * modCount是记录被修改次数(add方法执行,这个变量被改变),迭代器创建之前先将 modCount 赋值给 expectedModCount 每次遍历之前先检查 两个变量 相等不相等,不相等抛出异常
         */
        
        /**
         * 增强for循环调用的是迭代器
         */
        for (Student student : arrayList) {
            System.out.println(student.toString());
        }
    }
    public static void failSafe() {
        CopyOnWriteArrayList<Student> arrayList = new CopyOnWriteArrayList<>();
        /**
         * add()方法,上了锁,先复制一份源数组给新数组,在将长度+1并赋值上
         */
        arrayList.add(new Student("A"));
        arrayList.add(new Student("B"));
        arrayList.add(new Student("C"));
        arrayList.add(new Student("D"));
        /**
         * 加入断点,student.name.equals("C") 然后在加入一个"E",继续执行时结果为原来的结果不会抛出异常
         */
        /**
         * 增加for循环迭代器是 COWIterator,创建时先将数组复制一份给自己的成员变量,遍历时读取变量
         * 而 add() 添加时是一个新数组
         * 原理: 读写分离
         */
        for (Student student : arrayList) {
            System.out.println(student.toString());
        }
        System.out.println(arrayList);
    }
}

class Student {
    private String name;

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                '}';
    }
}
最后修改:2022 年 05 月 17 日 11 : 52 AM
赏杯咖啡喝 谢谢您~