首页 > 编程语言 >河北王校长源码之ArrayList

河北王校长源码之ArrayList

时间:2024-03-14 20:11:06浏览次数:18  
标签:index return int ArrayList elementData 源码 public 校长 size

ArrayListy

类结构

  • 继承AbstractList
  • 实现List
    • list基本方法
  • 实现RandomAccess
    • 支持随机访问(下标)
    • for效率高于迭代器(对比LinkedList)
  • 实现Cloneable
    • 浅克隆
  • 实现Serializable
    • 序列化

成员变量

  • 默认容量
    • private static final int DEFAULT_CAPACITY = 10;
  • 空数组
    • private static final Object[] EMPTY_ELEMENTDATA = {};
  • 默认容量数组
    • private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
  • 元素数组
    • transient Object[] elementData;
      • 不进行数组序列化
      • 重写序列化方法,序列化时取出每个元素进行

方法

构造方法

    // 提前创建数组容量,不适用于小数组
	public ArrayList(int initialCapacity) {
        // 构造函数指定容量>0,进行指定容量赋值
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } 
        // 构造函数指定容量=0,使用空数组
        else if (initialCapacity == 0) {
            this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+
                                               initialCapacity);
        }
    }
 	public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

添加方法

    public boolean add(E e) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }
	public void add(int index, E element) {
        // 越界检查
        rangeCheckForAdd(index);
        ensureCapacityInternal(size + 1);  
        System.arraycopy(elementData, index, elementData, index + 1,
                         size - index);
        elementData[index] = element;
        size++;
    }

容量方法

	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++;
        // 容量不足,扩容
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }
	// 扩容
    private void grow(int minCapacity) {
        // 计算扩容
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        // 新容量不足,使用最小容量为新容量
        if (newCapacity - minCapacity < 0)
            newCapacity = minCapacity;
        // 新容量不安全,使用最大安全容量
        if (newCapacity - MAX_ARRAY_SIZE >   0)
            newCapacity = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapacity);
    }
    private static int hugeCapacity(int minCapacity) {
        if (minCapacity < 0) // overflow
            throw new OutOfMemoryError();
        return (minCapacity > MAX_ARRAY_SIZE) ?
            Integer.MAX_VALUE :
            MAX_ARRAY_SIZE;
    }

复制方法

    public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }
    public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

收缩方法

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

包含方法

    public boolean contains(Object o) {
        return indexOf(o) >= 0;
    }
    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 Object clone() {
        try {
            ArrayList<?> v = (ArrayList<?>) super.clone();
            v.elementData = Arrays.copyOf(elementData, size);
            // 快速失败计数清零
            v.modCount = 0;
            return v;
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e);
        }
    }

转换数组方法

    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;
    }

得到方法

  	public E get(int index) {
        // 越界检查
        rangeCheck(index);
        return elementData(index);
    }
    private void rangeCheck(int index) {
        if (index >= size)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

设置方法

    public E set(int index, E element) {
        // 越界检查
        rangeCheck(index); 
        E oldValue = elementData(index);
        elementData[index] = element;
        // 返回旧值
        return oldValue;
    }

移除方法

    public E remove(int index) {
        // 边界检查
        rangeCheck(index);
        // 快速失败计数
        modCount++;
        E oldValue = elementData(index);
        int numMoved = size - index - 1;
        if (numMoved > 0)
            // 元素拷贝
            System.arraycopy(elementData, index+1, elementData, index, numMoved);
        // 置为null,开始gc工作
        elementData[--size] = null; 
        return oldValue;
    }  
    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; 
    }

清理方法

    public void clear() {
        // 快速失败计数
        modCount++;
        // 置为null,开始gc工作
        for (int i = 0; i < size; i++)
            elementData[i] = null;
        size = 0;
    }

添加集合方法

	// 布尔类型表示是否添加成功,慎用,添加空数组返回false
	public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew); 
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

    public boolean addAll(int index, Collection<? extends E> c) {
        rangeCheckForAdd(index);
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  
        int numMoved = size - index;
        if (numMoved > 0)
            System.arraycopy(elementData, index, elementData, index + numNew,
                             numMoved); 
        System.arraycopy(a, 0, elementData, index, numNew);
        size += numNew;
        return numNew != 0;
    }

范围移除方法

    // 包内访问权限和继承访问权限,左闭右开
	protected void removeRange(int fromIndex, int toIndex) {
        modCount++;
        int numMoved = size - toIndex;
        System.arraycopy(elementData, toIndex, elementData, fromIndex,
                         numMoved);
        int newSize = size - (toIndex-fromIndex);
        for (int i = newSize; i < size; i++) {
            elementData[i] = null;
        }
        size = newSize;
    }

添加越界判断方法

    private void rangeCheckForAdd(int index) {
        // 短路与,将高频率情况放置在前
        if (index > size || index < 0)
            throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
    }

移除集合方法

	// 移除ArrayList中与给定集合中元素相匹配的所有元素
	public boolean removeAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, false);
    }
	// 保留ArrayList中与给定集合中元素相匹配的所有元素
    public boolean retainAll(Collection<?> c) {
        Objects.requireNonNull(c);
        return batchRemove(c, true);
    } 
	// 批量移除或保留与给定集合相匹配或不匹配的元素
	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 {
            // 读取指针未结束,仍然存在元素,将剩余元素直接复制,写入指针延长
            if (r != size) {
                System.arraycopy(elementData, r, elementData, w, size - r);
                w += size - r;
            }
            // 写入指针未结束,存在移除
            if (w != size) {
                for (int i = w; i < size; i++)
                    elementData[i] = null;
                // 快速失败计数
                modCount += size - w;
                size = w;
                modified = true;
            }
        }
        return modified;
    }

序列化方法

	// 节省空间,无需考虑null序列化
	private void writeObject(java.io.ObjectOutputStream s)
        throws java.io.IOException{
        // 快速失败计数局部化(本身不能被序列化,防止被修改)
        int expectedModCount = modCount;
        // 基本信息写入输出流
        s.defaultWriteObject();
        // 写入 ArrayList 的大小 size
        s.writeInt(size);
        // 序列化每个元素
        for (int i=0; i<size; i++) {
            s.writeObject(elementData[i]);
        }
        if (modCount != expectedModCount) {
            // 业务高于序列化
            throw new ConcurrentModificationException();
        }
    }
    private void readObject(java.io.ObjectInputStream s)
        throws java.io.IOException, ClassNotFoundException {
        // 设置初始空数组
        elementData = EMPTY_ELEMENTDATA;
        // 恢复 ArrayList 的基本信息
        s.defaultReadObject();
        // 获取集合长度
        s.readInt(); 
        if (size > 0) {
            // 计算容量
            int capacity = calculateCapacity(elementData, size);
            // 检查数组的类型和容量的有效性
            SharedSecrets.getJavaOISAccess().checkArray(s, Object[].class, capacity);
            // 确保容量
            ensureCapacityInternal(size);
            Object[] a = elementData;
            for (int i=0; i<size; i++) {
                // 反序列化每个元素
                a[i] = s.readObject();
            }
        }
    }

特殊ArrayList

	// 元素必须固定,仅仅支持修改的场景(get(),set())
	List<Object> objects = Arrays.asList();
	// 返回空List场景(不支持任何操作)
	List<Object> objects = Collections.emptyList();

槽点

  • 继承AbstractList情况下,依旧实现List接口
  • addAll()方法在提供集合为空时,返回false
  • removeAll()retainAll()方法仅仅用Objects.requireNonNull(c)过滤null值,对空数组没有处理
  • batchRemove()内部使用try catch并未捕获异常
  • Collections.emptyList()提供的空List不支持操作,但实现了RandomAccess

优点

  • E set(int index, E element)E remove(int index)返回旧值
  • 越界判断,短路与,将高频率情况放置在前
  • for循环遍历,提高性能
  • 重写序列化方法,不序列化整个数组,取出元素依次序列化

标签:index,return,int,ArrayList,elementData,源码,public,校长,size
From: https://www.cnblogs.com/faetbwac/p/18073165

相关文章

  • Linux源码安装nginx1.20.2
    下面是关于Linux源码安装nginx1.20.2的操作流程目录前言1,安装准备1.1下载安装包 1.2上传安装包1.3解压  1.4关闭防火墙和selinux2,安装 nginx依赖库以及编译环境2.1安装nginx依赖库 2.2执行configure脚本生成makefile配置文件2.2.1可能出现的错误 3,......
  • List集合-Arraylist
    Arraylist创建集合packageeight.list.arraylist;importjava.util.ArrayList;importjava.util.List;publicclassStudent{publicstaticvoidmain(String[]args){//创建集合//Listaa=newArrayList();ArrayListaa=newAr......
  • PG14:auth_delay 插件源码分析
    auth_delay让服务器在报告身份验证失败前短暂暂停,以增加对数据库密码进行暴力破解的难度。需要注意的是,这对阻止拒绝服务攻击毫无帮助,甚至可能加剧攻击,因为在报告身份验证失败前等待的进程仍会占用连接。要使用这个模块必须要在postgresql.conf中配置参数shared_preload_libr......
  • 基于springboot的高校招生系统(含源码+sql+视频导入教程+文档+PPT)
    ......
  • java毕设安卓基于Android的志愿者服务系统(开题+源码)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容一、研究背景在当今信息化社会,移动互联网技术的迅猛发展正深刻改变着人们的生活方式。特别是在社会公益领域,志愿者服务作为社会文明进步的重要标志,其组织与管......
  • 学生考勤系统|基于Springboot的大学生考勤系统设计与实现(源码+数据库+文档)
    大学生考勤系统目录目录基于Springboot的大学生考勤系统设计与实现一、前言二、系统功能设计三、系统实现1、系统登录注册2、管理员功能模块四、数据库设计1、实体ER图 2、具体的表设计如下所示:五、核心代码 六、论文参考 七、最新计算机毕设选题推荐八、源码......
  • 基于java+springboot+vue实现的物业管理系统(文末源码+Lw+ppt)23-23
    摘  要快速发展的社会中,人们的生活水平都在提高,生活节奏也在逐渐加快。为了节省时间和提高工作效率,越来越多的人选择利用互联网进行线上打理各种事务,通过线上物业管理系统也就相继涌现。与此同时,人们开始接受方便的生活方式。他们不仅希望页面简单大方,还希望操作方便,可以快......
  • 基于java+springboot+vue实现的停车场管理系统(文末源码+Lw)23-258
    摘 要如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统停车场管理系统信息管理难度大,容错率低,管理人员处理数据费工费时,所以专门为解决这个难题开发了一个停车场管......
  • 基于java+springboot+vue实现的停车场管理系统(文末源码+Lw)23-258
    摘 要如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统停车场管理系统信息管理难度大,容错率低,管理人员处理数据费工费时,所以专门为解决这个难题开发了一个停车场管......
  • 基于java+springboot+vue实现的美食网站系统(文末源码+Lw+ppt)23-55
    摘   要互联网的兴起从本质上改变了整个社会对信息的管理方式,我国从上个世纪90年代互联网兴起之时,就产生了通过网络进行系统管理的想法。但是由于在互联网上的信誉难以认证、网络的法规政策不健全等一系列的原因,限制了网上信息管理发展的步伐。进入21世纪以后,随着整个社会......