首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Java源码系列1——ArrayList

本文简单介绍了 ArrayList,并对扩容,添加,删除操作的源代码做分析。能力有限,欢迎指正。 ArrayList是什么? ArrayList 就是数组列表,主要用来装载数据。...正常使用场景中,ArrayList 都是用来查询,不会涉及太频繁的增删,如果涉及频繁的增删,可以使用 LinkedList。如果需要线程安全就使用 Vector。...Vector 是 ArrayList 的线程安全版本,实现方式就是在所有方法加上synchronized,性能较差。 如何扩容? 因为数组的大小是固定,当容量超出了现有数组的大小,就需要进行扩容。...原因有两点: 新增就要检测容量够不够,如果不够就需要扩容 尾部新增比较快,如果是在数组头部或者中部新增就会慢很多,因为要把后面的元素全部往后移一位 把元素往后移一位使用的是复制 System.arraycopy...效率和新增差不多,都是要移动元素,但是不需要检查容量和扩容。

34330

玩转Java中的ArrayList:常用操作技巧和方法总结

线程不安全:ArrayList不是线程安全的,如果有多个线程同时访问同一个ArrayList实例,可能会出现竞争条件。非同步:ArrayList不是同步的,不保证多个线程并发访问时的安全性。...其中,无参构造函数初始化为默认容量10,带初始容量参数的构造函数会检查参数是否合法,如果小于等于0则抛出IllegalArgumentException异常,带集合参数的构造函数会将集合转化为数组并存放在...常用操作技巧和方法添加元素  在ArrayList中添加元素最基本的方法就是add()方法,该方法有两种重载形式,一种是无参的add()方法,一种是有参数的add(int index, E element...的定义和特点,详细描述了它的常用操作技巧和方法,通过源代码解析让读者了解ArrayList的底层实现原理,通过应用场景案例分析,探讨ArrayList的使用场景和优缺点,以帮助读者在实际开发中更好地选择数据结构...总结  本文详细介绍了Java中的ArrayList类,包括其定义和特点、常用操作技巧和方法、源代码解析、应用场景案例分析以及优缺点分析等方面。

77621
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    ArrayList的扩容机制

    在Java中,ArrayList是一个使用非常频繁的集合类型,它的底层是Object数组,所以它拥有数组所拥有的特性,比如支持随机访问,所以查询效率高,但插入数据需要移动元素,所以效率低。...先来看看若是调用ArrayList的无参构造方法,会发生什么?...所以,如果你只知道新容量是旧容量的1.5倍,这个问题你就无法知道。事实上,ArrayList底层是通过移位操作计算得到的新容量。...,所以它将返回DEFAULT_CAPACITY和minCapacity中较大的那个,结果是minCapacity较大,所以返回11,这就导致addAll()方法执行结果后ArrayList的容量为11。...addAll()方法总是选择扩容一次后的容量与旧容量加上添加的元素个数的容量中取一个最大值作为新的容量,比如:当前ArrayList中有10个元素,而addAll()方法需要添加6个元素,当ArrayList

    67120

    JAVA集合之ArrayList源码分析

    简介 ArrayList的概述 ArrayList是我们开发中非常常用的数据存储容器之一,其底层是数组实现的,我们可以在集合中存储任意类型的数据,ArrayList是线程不安全的,非常适合用于对元素进行查找...ArrayList集合源码分析 首先看看ArrayList的结构图 分析结构 为什么要先继承AbstractList,而让AbstractList先实现List?...这里是有一个思想,接口中全都是抽象的方法,而抽象类中可以有抽象方法,还可以有具体的实现方法,正是利用了这一点,让AbstractList是实现接口中一些通用的方法,而具体的类,如ArrayList就继承这个...这其实是一个mistake,因为他写这代码的时候觉得这个会有用处,但是其实并没什么用,但因为没什么影响,就一直留到了现在。...//上方有分析到,该方法就是检查下标的合法性的 rangeCheck(index); //从元素数组中获取数据 E oldValue = elementData(index

    26730

    java集合【8】-- ArrayList接口源码解析

    其底层实际上是数组实现的,那为什么我们使用的时候只管往里面存东西,不用关心其大小呢?因为ArrayList封装了这样的功能,容量可以动态按需变化,不需要使用者关心。扩容之后不会自动缩小容量。 2....关于上面的transient,找到一个靠谱的说法: 在ArrayList中的elementData这个数组的长度是变长的,java在扩容的时候,有一个扩容因子,也就是说这个数组的长度是大于等于ArrayList...构造方法 构造方法有三个,可以指定容量,可以指定初始的元素集合,也可以什么都不指定。...好像上面的源代码中我们没有看到,其实是有的,所谓扩容嘛,就是容量不够了,那么容量不够的时候只会发生在初始化一个集合的时候或者是增加元素的时候,所以是在add()方法里面去调用的。...如果元素是默认初始haul的空数据,那么所需要的最小容量就是默认容量和最小容量对比,两者取最大,也就是突然有加入有6个元素加到集合中来,那么默认容量是10,会直接初始化为10,如果一下子有11个元素加进来

    37700

    Java ArrayList扩容的原理

    (ArrayList是有索引的)。...当这些都准备好了之后,就可以开始加入元素了——第一次加入元素调用ArrayList中的add方法,传入想要加入集合的元素,然后接收到返回值(但ArrayList返回值没什么意义),元素就成功加入集合了。...但数组的长度发生了什么变化?还是进入源码: 首先modCount这个变量会自增一次(这个变量是用来记录集合的操作次数的,对于扩容原理用处不大。)...grow的重载方法中: 这个重载的grow方法中的参数是minCapacity,其意义是“数组扩容后的最小容量”,现在数组扩容后的最小容量是1(size+1),有一个叫oldCapcity变量,用来记录...后续添加的扩容现在ArrayList中已经有了1个元素了,size也指向了1,elementData的大小也来到了10,所以说当我们再调用9次add方法,都是直接添加元素就成功了(此时是添加到第10个元素

    11210

    java集合【8】——— ArrayList源码分析

    其底层实际上是数组实现的,那为什么我们使用的时候只管往里面存东西,不用关心其大小呢?因为ArrayList封装了这样的功能,容量可以动态按需变化,不需要使用者关心。扩容之后不会自动缩小容量。 2....关于上面的transient,找到一个靠谱的说法:在ArrayList中的elementData这个数组的长度是变长的,java在扩容的时候,有一个扩容因子,也就是说这个数组的长度是大于等于ArrayList...构造方法 构造方法有三个,可以指定容量,可以指定初始的元素集合,也可以什么都不指定。...好像上面的源代码中我们没有看到,其实是有的,所谓扩容嘛,就是容量不够了,那么容量不够的时候只会发生在初始化一个集合的时候或者是增加元素的时候,所以是在add()方法里面去调用的。...如果元素是默认初始haul的空数据,那么所需要的最小容量就是默认容量和最小容量对比,两者取最大,也就是突然有加入有6个元素加到集合中来,那么默认容量是10,会直接初始化为10,如果一下子有11个元素加进来

    31120

    ArrayList中几个不为人知的事情

    今天学习下ArrayList的源代码,不同于其他人写的博客,很多都是翻译源代码中的注释,然后直接贴到文章中去。小编打算换一种书写风格,带着问题看源码可能收获会更大,本文将围绕着下面几个问题展开讨论。...一、问题产生 1、为什么ArrayList集合中存储元素的容器声明为transient Object[] elementData;?...二、问题解答 1、为什么ArrayList集合中存储元素的容器声明为transient Object[] elementData;?...上面第3小节我们查看了ArrayList迭代器的源代码,我们都知道,如果在迭代的过程中调用非迭代器内部的remove或者clear方法将会抛出ConcurrentModificationException...那我们怎么做才能不报错有想在迭代过程中增加或者删除数据呢?答案是使用迭代器内部的remove()方法。

    31110

    教你如何高效使用Java中的ArrayList

    源代码解析  ArrayList的源代码非常长,这里只对其中一些比较重要的方法进行分析。...首先,它会调用rangeCheck方法,该方法用于检查指定的下标是否越界。然后,它会将元素从数组中删除,并返回该元素的值。...在next方法中,它会检查是否有其他线程对ArrayList进行修改,如果有则抛出ConcurrentModificationException异常。如果没有,则返回下一个元素并将游标+1。...this.elementData = EMPTY_ELEMENTDATA; }}  ArrayList类有三个构造函数,分别是无参构造函数、指定初始容量的构造函数和从其他集合类中构造的构造函数。...ArrayList的源代码非常长,但其实现原理比较简单,主要涉及到数组的扩容和元素的移动等操作。ArrayList具有很高的操作效率,但在删除和插入元素时,需要进行数组元素的移动和复制,因此速度较慢。

    34581

    Java中的ArrayList的设计思想与底层原理剖析

    Java中的ArrayList的设计思想与底层原理剖析 当使用Java的ArrayList集合类时,了解其设计思想、底层原理和与传统数组相比的优势是很重要的。...它根据当前容量和所需的最小容量来决定是否需要扩容。 grow()方法实现了扩容的细节。它计算新的容量并使用Arrays.copyOf()方法将旧数组复制到新数组中。...支持泛型: ArrayList可以存储任意类型的对象,并且能够在编译时进行类型检查,避免了类型转换错误。...源代码解析 下面是对于源代码的详细的注释和解释: public class ArrayList extends AbstractList implements List, RandomAccess...ArrayList通过动态数组管理元素,自动进行容量调整,并提供了丰富的方法和功能来解决各种复杂问题。详细的代码注释帮助我们更好地理解源代码,并正确使用ArrayList这个强大的集合类。

    11310

    java集合【7】——— List接口超级详细源码分析

    其底层实际上是数组实现的,那为什么我们使用的时候只管往里面存东西,不用关心其大小呢?因为ArrayList封装了这样的功能,容量可以动态变化,不需要使用者关心。...在哪里调用的呢?其实就是在对象流中,通过反射的方式进行调用的,这里就不展开了,下次一定!!!有兴趣可以看看。 如果我们创建的时候不指定大小,那么就会初始化一个默认大小为10。...好像上面的源代码中我们没有看到,其实是有的,所谓扩容嘛,就是容量不够了,那么容量不够的时候只会发生在初始化一个集合的时候或者是增加元素的时候,所以是在add()方法里面去调用的。...,这里指的是节点里面的item,从源码中可以看出,只会移除第一个满足条件的元素,成功移除则返回true,否则将返回false。...使用iterator,您只能检查下一个元素是否可用,但是在listiterator中,您可以检查上一个和下一个元素。使用listiterator,您可以在遍历的任何时间添加新元素。

    59640

    揭秘Java中的瑞士军刀——ArrayList源码解析

    它为我们提供了一种方便的方式来管理和操作一个动态数组,但是你是否曾经停下来3思考过它是如何工作的呢?它的内部机制是什么?...如果你对这些问题感到好奇,那么让我们一起深入到Java的核心库中去,探索ArrayList的源代码,揭开它的神秘面纱。...如果传入的elementData是默认的空元素数组,则返回默认容量和最小容量中的较大值;否则,返回传入的最小容量 private static int calculateCapacity(Object[...如果传入的elementData是默认的空元素数组,则返回默认容量和最小容量中的较大值;否则,返回传入的最小容量 private static int calculateCapacity(Object[...)和expectedModCount(表示ArrayList在进入该方法时期望的修改次数)来判断是否有并发修改发生 //果两者不相等,说明在当前方法调用期间有其他线程对ArrayList进行了修改

    19550

    java集合【7】-- List接口源码解析

    其底层实际上是数组实现的,那为什么我们使用的时候只管往里面存东西,不用关心其大小呢?因为ArrayList封装了这样的功能,容量可以动态变化,不需要使用者关心。...在哪里调用的呢? 其实就是在对象流中,通过反射的方式进行调用的,这里就不展开了,下次一定!!!有兴趣可以看看。 如果我们创建的时候不指定大小,那么就会初始化一个默认大小为10。...好像上面的源代码中我们没有看到,其实是有的,所谓扩容嘛,就是容量不够了,那么容量不够的时候只会发生在初始化一个集合的时候或者是增加元素的时候,所以是在add()方法里面去调用的。...,这里指的是节点里面的item,从源码中可以看出,只会移除第一个满足条件的元素,成功移除则返回true,否则将返回false。...使用iterator,您只能检查下一个元素是否可用,但是在listiterator中,您可以检查上一个和下一个元素。 使用listiterator,您可以在遍历的任何时间添加新元素。

    64500

    ArrayList 可以完全替代数组吗?

    ♀️疑问 5: 为什么 ArrayList 的最大容量是 MAX_VALUE - 8,一定会减 8 吗? 这些问题我们在分析源码的过程中回答。疑问这么多,ArrayList 瞬间不香了。...添加前会先检查数据容量,不足会先扩容: 在使用无参构造器初始化时,首次添加元素时会直接扩容到 10 的容量; 在其他情况,会直接扩容到旧容量的 1.5 倍,而不是扩容到最小容量要求。...在 《阿里巴巴 Java 开发手册》中,有关于 ArrayList#subList API 的规定。为什么阿里巴巴要做这样的限制呢?...而在 ArrayList#toArray() 方法中,返回值的类型是 Object[] 类型,有类型错误风险。...,而是指向全局空数组,这是懒初始化的策略; 3、在添加数据时会先检查数据容量,不足会先扩容。

    75030

    ArrayList 的扩容机制

    什么是ArrayList的扩容机制? ArrayList是Java中常用的动态数组实现类,它可以根据需要自动调整大小。...当我们向ArrayList添加元素时,如果当前容量不足以容纳新元素,ArrayList会自动进行扩容操作,即增加底层数组的长度。 2. 为什么需要ArrayList的扩容机制?...扩容触发条件:当ArrayList的size超过当前容量时,就会触发扩容操作。 扩容策略:ArrayList在扩容时,会创建一个新的更大容量的数组,并将原有元素复制到新数组中。...具体的扩容流程如下: 当向ArrayList添加元素时,会先检查当前容量是否足够。如果不足,则进行扩容操作。 扩容时,根据增长因子计算新的容量,并创建一个新的数组。...将原有数组中的元素复制到新数组中。 更新ArrayList内部的引用,指向新数组。 添加新元素到新数组中。 4.

    99920

    【Java提高十六】集合List接口详解

    在每次向容器中增加元素的同时都会进行容量检查,当快溢出时,就会进行扩容操作。所以如果我们明确所插入元素的多少,最好指定一个初始容量值,避免过多的进行扩容操作而浪费时间、效率。...在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,所以如果我们知道具体业务数据量,在构造ArrayList时可以给ArrayList指定一个初始容量...在这里有一个疑问,为什么每次扩容处理会是1.5倍,而不是2.5、3、4倍呢?通过google查找,发现1.5倍的扩容是最好的倍数。...从该方法有两个遍历方向中我们也可以看出LinkedList是双向链表,这也是在构造方法中为什么需要将header的前、后节点均指向自己。...该方法的源代码如下: ?

    1.1K31

    ArrayList 源码解析,炒鸡详细!!!

    3ArrayList解析 我们提到数组的特点是大小固定,ArrayList的底层是基于数组来实现容量的大小动态变化的,那我们一起来结合源码看看,是如何实现这一功能的。...class access // 实际大小容量 private int size; 我们发现有两个一样的空数组对象,为什么要用两个呢?...源代码中也进行来解释 We distinguish this from EMPTY_ELEMENTDATA to know how much to inflate when first element...2、将源数组拷贝到新的数组中,重新复制给elementData; 3、在index=10的位置添加元素 add index 移动拷贝 在集合中已经有了5个元素了。...基本上都是基于索引来访问的。 到这里我们已经总结了很多常用的方法,在ArrayList中还有非常多的方法,例如迭代器Iterator、suList操作等等。

    20910

    Java集合源码分析(一)ArrayList

    这里我推荐的方法是:     1)看继承结构       看这个类的层次结构,处于一个什么位置,可以在自己心里有个大概的了解。     ...这里是有一个思想,接口中全都是抽象的方法,而抽象类中可以有抽象方法,还可以有具体的实现方法,正是利用了这一点,让AbstractList是实现接口中一些通用的方法,而具体的类,       如ArrayList...这其实是一个mistake,因为他写这代码的时候觉得这个会有用处,但是其实并没什么用,但因为没什么影响,就一直留到了现在。       ...,意味着ArrayList中可以存放null元素的。...(只检查是否大于size,而没有检查是否小于0),值得注意的是,在get函数中存在element函数,element函数用于返回具体的元素,具体函数如下: E elementData(int index

    1K60

    「实实在在面试」—List和Map集合面试合集【含讲解视频】

    如何扩容 什么时候发生扩容: 每次添加的时候 会检查要不要扩容 执行ensureCapacityInternal 确保内部容量 ?...1598943762994 扩容的条件:当底层数组 四分之三 的位置有了元素 就扩容 HashMap是怎么处理hash碰撞的?...Java7在多线程操作 HashMap 时可能引起死循环,原因是扩容转移后前后链表顺序倒置,在转移过程中修改了原来链表中节点的引用关系。 HashMap的扩容机制? 什么时候扩容?...(risize) HashMap的底层是数组,数组的容量有限,到达一定的数量就会进行扩容。 影响扩容时机的因素有两个: 什么意思呢?当数组中75%的位置满了的时候,就会进行扩容。...所以长度改变了,所有的元素复制到新数组中需要重新计算位置 HashMap 线程安全吗? 不是 有哪些线程安全的 Map Hashtable ?

    46710
    领券