ArrayList底层结构和源码分析

这篇具有很好参考价值的文章主要介绍了ArrayList底层结构和源码分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

  ArrayList的注意事项

1.permits all elements, including null,ArrayList 可以加入null,并且多个

2.ArrayList是由数组来实现数据存储的

3.ArrayList 基本等同于Vector,除了ArrayList是线程不安全(执行效率高)看源码.在多线程情况下,不建议使用ArrayList

代码演示:

package idea.chapter14.collection_;

import java.util.ArrayList;

/**
 * 演示ArrayList的注意事项和使用细节
 */
@SuppressWarnings({"all"})
public class ArrayListDetail {
    public static void main(String[] args) {

        //ArrayList 是线程不安全的, 可以看源码 没有 synchronized修饰
        /*
            public boolean add(E e) {
                ensureCapacityInternal(size + 1);  // Increments modCount!!
                elementData[size++] = e;
                return true;
            }
         */
        ArrayList arrayList = new ArrayList();
        arrayList.add(null);
        arrayList.add("jack");
        arrayList.add(null);
        arrayList.add("hsp");
        System.out.println(arrayList);
    }
}

ArrayList源码分析结论

ArrayList的底层操作机制源码分析(重点,难点.)

1.ArrayList中维护了一个Object类型的数组elementData.[debug看源码]

transient Objectl] elementData; //transient 表示瞬间,短暂的,表示该属性不会被序列化

2)当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第1次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍。

3)如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍。

源码分析:文章来源地址https://www.toymoban.com/news/detail-424126.html

    /*
    //第一步
    先调用ArrayList的无参构造器,去创建一个空数组
        public ArrayList() {
            this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
        }

    //第二步
    调用add方法
    1.先确定是否要扩容
    ensureCapacityInternal(size + 1);这个方法就是判断是否要进行扩容,
    2.然后进行赋值

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

    //第三步
    指向ensureCapacityInternal方法,进入方法后先进行判断,
    private void ensureCapacityInternal(int minCapacity) {
        //我们第一次进行扩容的时候,此时elementData是null,因此会进入if语句
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
             DEFAULT_CAPACITY这是一个默认值,是10 minCapacity 是1
             因此Nath.max方法会在两个数中选出一个最大值赋值给minCapactiy 所以此时minCapacity就是10
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

private void ensureExplicitCapacity(int minCapacity) {
    modCount++;//用来记录集合被修改的次数,主要是防止同时有多个线程去修改,如果有那么会抛出一个异常

    // overflow-conscious code
    minCapacity是我需要的最小容量
    elementData.length
    也就是说,我们需要10个的大小,但是你这个数组能给我提供的只有0 两数相减的结果去过大于0,说明就需要扩容了
    if (minCapacity - elementData.length > 0)
        //如果满足上面if的条件,那么就真的扩容
        grow(minCapacity);//真正的扩容的方法
}


//真的扩容的方法
private void grow(int minCapacity) {
    // overflow-conscious code
    第一次进行扩容的时候,因为数组是空 ,所以elementData.length就是0 所以把0赋值给了oldCapacity
    int oldCapacity = elementData.length;
    然后oldCapacity>>1 也就是把oldCapacity除2 但是因为oldCapacity是0 所以结果还是0 因此oldCapacity+(oldCapacity>>1)的结果还是0.把这个结果赋给newCapacity也是0
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    然后newCapacity - minCapacity  因为minCapacity是10 所以0-10小于0
    if (newCapacity - minCapacity < 0)
        然后就进入if语句 把 minCapacity 赋值给newCapacity 所以newCapacity的结果就是10 这也就是为什么,第一次扩容的时候 是10 第二次就按照1.5倍进行扩容
        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);
}

     */
package idea.chapter14.list_;

import java.util.ArrayList;

@SuppressWarnings({"all"})
public class ArrayListSource {
    public static void main(String[] args) {


        //注意Idea 默认情况下,Debug 显示的数据是简化后的,如果希望看到完整的数据
        //需要做设置.
        //使用无参构造器创建ArrayList对象
        ArrayList list = new ArrayList();
        //ArrayList list = new ArrayList(8);
        //使用for给list集合添加 1-10数据
        for (int i = 1; i <= 10; i++) {
            list.add(i);
        }
        //使用for给list集合添加 11-15数据
        for (int i = 11; i <= 15; i++) {
            list.add(i);
        }
        list.add(100);
        list.add(200);
        list.add(null);


        /*
        //第一步
        先调用ArrayList的无参构造器,去创建一个空数组
            public ArrayList() {
                this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
            }

        //第二步
        调用add方法
        1.先确定是否要扩容
        ensureCapacityInternal(size + 1);这个方法就是判断是否要进行扩容,
        2.然后进行赋值

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

        //第三步
        指向ensureCapacityInternal方法,进入方法后先进行判断,
        private void ensureCapacityInternal(int minCapacity) {
            //我们第一次进行扩容的时候,此时elementData是null,因此会进入if语句
            if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
                 DEFAULT_CAPACITY这是一个默认值,是10 minCapacity 是1
                 因此Nath.max方法会在两个数中选出一个最大值赋值给minCapactiy 所以此时minCapacity就是10
                minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
            }

            ensureExplicitCapacity(minCapacity);
        }

    private void ensureExplicitCapacity(int minCapacity) {
        modCount++;//用来记录集合被修改的次数,主要是防止同时有多个线程去修改,如果有那么会抛出一个异常

        // overflow-conscious code
        minCapacity是我需要的最小容量
        elementData.length
        也就是说,我们需要10个的大小,但是你这个数组能给我提供的只有0 两数相减的结果去过大于0,说明就需要扩容了
        if (minCapacity - elementData.length > 0)
            //如果满足上面if的条件,那么就真的扩容
            grow(minCapacity);//真正的扩容的方法
    }


    //真的扩容的方法
    private void grow(int minCapacity) {
        // overflow-conscious code
        第一次进行扩容的时候,因为数组是空 ,所以elementData.length就是0 所以把0赋值给了oldCapacity
        int oldCapacity = elementData.length;
        然后oldCapacity>>1 也就是把oldCapacity除2 但是因为oldCapacity是0 所以结果还是0 因此oldCapacity+(oldCapacity>>1)的结果还是0.把这个结果赋给newCapacity也是0
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        然后newCapacity - minCapacity  因为minCapacity是10 所以0-10小于0
        if (newCapacity - minCapacity < 0)
            然后就进入if语句 把 minCapacity 赋值给newCapacity 所以newCapacity的结果就是10 这也就是为什么,第一次扩容的时候 是10 第二次就按照1.5倍进行扩容
            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);
    }

         */
    }
}

到了这里,关于ArrayList底层结构和源码分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 源码分析——HashMap(JDK1.8)源码+底层数据结构分析

    HashMap 主要用来存放键值对,它基于哈希表的Map接口实现,是常用的Java集合之一。 JDK1.8 之前 HashMap 由 数组+链表 组成的,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的(“拉链法”解决冲突).JDK1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈

    2024年02月13日
    浏览(30)
  • Java实现ArrayList和底层源码讲解

    🎉🎉🎉 点进来你就是我的人了 博主主页: 🙈🙈🙈戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔 🦾🦾🦾 目录 一. 模拟实现ArrayList​编辑 1.定义顺序顺序表 2. 函数实现 (1) 打印顺序表display()函数 (2) 新增元素函数add() (默认在数组最后新增) (3) 在 pos 位置新增元

    2023年04月16日
    浏览(29)
  • Java中ArrayList的底层扩容机制和Vector的底层扩容机制,以及ArrayList和Vector的对比与选择。附源码

    在 Java 的 ArrayList 中,当数组的容量不足以存储新元素时,会触发扩容操作。ArrayList 的底层使用数组来存储元素,而扩容机制主要涉及到创建一个更大的数组,并将现有元素复制到新数组中。ArrayList 支持无参扩容和有参扩容两种机制。 无参扩容机制 : 无参扩容是指 首次的

    2024年02月11日
    浏览(27)
  • 源码分析——ArrayList源码+扩容机制分析

    ArrayList 的底层是数组队列,相当于动态数组。与 Java 中的数组相比,它的容量能动态增长。在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。 ArrayList 继承于 AbstractList ,实现了 List , RandomAccess , Cloneable , ja

    2024年02月14日
    浏览(35)
  • Java集合框架之ArrayList源码分析

    ArrayList是Java提供的线性集合,本篇笔记将从源码(java SE 17)的角度学习ArrayList: 什么是ArrayList? ArrayList底层数据结构是怎么实现的? 作为一个容器,分析增删改查的过程 ArrayList的扩容机制 由ArrayList的定义可知,ArrayList继承了AbstractList抽象类,实现了List、RandomAccess、Cloneabl

    2024年02月07日
    浏览(46)
  • LinkedList部分底层源码分析

    JDK版本为1.8.0_271,以插入和删除元素为例,LinkedList部分源码如下: 插入删除结点的过程如图所示: 只有1个元素的LinkedList 包含4个元素的LinkedList add(E e)方法 add(int index,E e)方法 remove(Object obj)方法 remove(int index)方法

    2024年04月13日
    浏览(24)
  • MyBatis底层源码分析

    🎄欢迎来到@边境矢梦°的csdn博文🎄 🎄本文主要梳理MyBatis底层源码分析 🎄 🌈我是边境矢梦°,一个正在为秋招和算法竞赛做准备的学生🌈 🎆喜欢的朋友可以关注一下 🫰🫰🫰 ,下次更新不迷路🎆 Ps: 月亮越亮说明知识点越重要 (重要性或者难度越大)🌑🌒🌓🌔🌕 

    2024年02月08日
    浏览(32)
  • ArrayList底层的实现原理

    ArrayList底层的实现原理 ArrayList底层是用动态数组实现的 ArrayList初始化容量为0,当第一次添加数据的时候才会初始化为10。 ArrayList在进行扩容的时候是原来容量的1.5倍,每次扩容都需要拷贝数组。 ArrayList在添加数据的时候 确保数组已使用长度size+1之后足够存下下一个数据 计

    2024年01月22日
    浏览(31)
  • Java进阶(3)——手动实现ArrayList & 源码的初步理解分析 & 数组插入数据和删除数据的问题

    1.ArrayList的结构分析,可迭代接口,是List的实现; 2.数组增加元素和删除元素的分析,何时扩容,如何扩容; 3.插入数据的复杂度O(N); 4.数组特点:查找和修改容易O(1);增加和删除复杂O(N); 增加元素 如果放不下怎么办?如何扩容? 扩容后如何操作? 扩容:每次为原来的

    2024年02月12日
    浏览(32)
  • SpringBoot:自动配置源码底层原理分析

    声明:原文作者:yuan_404 配置文件到底能写什么?怎么写? SpringBoot 官方文档中有大量的配置,我们无法全部记住 ,下面我们就梳理一下最核心的几个部分进行讲解。 以HttpEncodingAutoConfiguration(Http编码自动配置)为例解释自动配置原理; @Configuration(proxyBeanMethods = false) 表示

    2023年04月09日
    浏览(27)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包