第二种方式是编码规范的要求我们这么写的,传入一个初始化的容量。这么做的目的主要是防止向集合中添加数据时,由于集合扩容导致的性能下降问题。...其实他的本质就是一个Object[] , 我们每次向List中添加一个元素,他都会把元素存储到他的一个Object[] 中。那么问题是,我创建一个多大的数组合适呢?...当我们向集合中添加元素的时候,集合首先会判断当前的数组容量能否容纳得下所需添加的元素,如果容纳不下,就会触发自动扩容机制。...从jdk8开始,集合不是你new完了就把空间创建出来的,从代码也可以看出来,我们new完的集合(0参和无参),实际上就给了一个空数组,只有当我们向集合中添加元素的时候,才会根据长度初始化数组的长度。...也就是当我们向集合中添加元素的时候,如果元素个数小于10,那么这个结果就是10, 如果元素个数大于10了,就取当前的最大值。
线程B也向此ArrayList 添加元素,因为此时 Size 仍然等于 0 (注意哦,我们假设的是添加一个元素是要两个步骤哦,而线程A仅仅完成了步骤1),所以线程B也将元素存放在位置0。...四、ArrayList的主要成员变量 private static final int DEFAULT_CAPACITY = 10; 当ArrayList的构造方法中没有显示指出ArrayList的数组长度时...private static final Object[] EMPTY_ELEMENTDATA = {}; 当ArrayList的构造方法中显示指出ArrayList的数组长度为0时,类内部将EMPTY_ELEMENTDATA...的数组长度时,类内部使用默认缺省时对象数组为DEFAULTCAPACITY_EMPTY_ELEMENTDATA。...这也解释了为什么要把情况分为需要查找的对象是否为空两种情况讨论,不然的话空对象调用equals方法则会产生空指针异常。
size变量跟踪ArrayList的大小。当你向ArrayList中添加元素时,它们会存储在elementData数组中,并相应地更新size。...() 初始化时,ArrayList 的内部数组 elementData 初始化为一个空数组(EMPTY_ELEMENTDATA),并在添加第一个元素时才进行实际的初始化和分配。...默认情况下,ArrayList 的初始容量为 10,即创建一个长度为 10 的空数组。...当向 ArrayList 添加元素时,如果容量不足,会触发扩容机制,将数组长度扩大为原来的 1.5 倍。...当我们向ArrayList 中添加元素(调用add()或者addAll())时,都调用了一个ensureCapacityInternal()方法 我们来看源码: add() public boolean
该类封装了一个动态再分配的Object【】数组,每一个类对象都有一个capacity属性,表示他们所封装的Object【】数组长度,当向ArrayList中添加元素时,该属性值会自动增加。...ArrayList的用法和Vector向类似,但是Vector是一个较老的集合,具有很多缺点,不建议使用。...说明:底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的。...当我们调用add方法时,实际上的函数调用如下: ? 说明:程序调用add,实际上还会进行一系列调用,可能会调用到grow,grow可能会调用hugeCapacity。...,那么elementData被初始化为大小为6的Object数组,在调用add(8)方法时,具体的步骤如下: ?
stringValues = new ArrayList(); //可以向数组中添加任何类型的对象 stringValues.add(1); //问题1...然而,当我们使用数据的时候,需要将获取的Object对象转换为我们期望的类型(String),如果向集合中添加了非预期的类型(如Integer),编译时我们不会收到任何的错误提示。...我们在介绍泛型时指出向ArrayList中插入String类型的对象,编译时会报错。现在为什么又可以了呢?...当我们从集合中获取元素时,默认会将对象强制转换成泛型参数指定的类型(这里是Integer),如果放入了非法的对象这个强制转换过程就会出现异常。...那么当我们使用arrayList2引用用get()方法取值的时候,返回的都是String类型的对象,可是它里面实际上已经被我们存放了Object类型的对象,这样,就会有ClassCastException
extends E> c):向集合中添加一个集合的元素。...E:判断功能 boolean isEmpty():判断集合是否为空。 boolean contains(Object o):判断集合中是否存在指定的元素。...当我们序列化对象时,如果对象中某个属性不进行序列化操作,那么在该属性前添加transient修饰符即可实现;例如: private transient Object[] elementData; 那么,...ArrayList在添加元素时,可能会对elementData数组进行扩容操作,而扩容后的数组可能并没有全部保存元素。...例如:我们创建了new Object[10]数组对象,但是我们只向其中添加了1个元素,而剩余的9个位置并没有添加元素。
} 注意,当我们创建的时候,elementData这个数组的数组长度为0,但当我们添加数据的时候他的默认长度才会变成10。...比较重要的几个方法 Add ArrayList已经是具体的实现类了,所以其实现了list接口中所有的定义方法。首先前面说到ArrayList的默认大小为0,只有第一次添加数据的时候才会设为10。...(注意,这个方法不会缩减数组的长度,只是将最后一位置空而已…) 下面是根据对象进行remove。它会循环编译所有对象,找到你要移除对象的索引位置。...前面我们介绍了将数组元素置为空后,它的数组大小没变。那么通过clear方法。他的数组大小会变吗?...(包括null值)去除,例如:数组长度为10,其中只有前三个元素有值,其他为空,那么调用该方法之后,数组的长度变为3。
Java的serialization提供了一种持久化对象实例的机制。当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。...例如初次添加时,size为0,add将elementData[0]赋值为e,然后size设置为1(类似执行以下两条语句elementData[0]=e;size=1)。...具体实现如下: (1) 当调用下面这两个方法向数组中添加元素时,默认是添加到数组中最后一个元素的后面。内存结构变化如下: ?...调整数组容量ensureCapacity (1)从上面介绍的向ArrayList中存储元素的代码中,我们看到,每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容...这种操作的代价是很高的,因此在实际使用时,我们应该尽量避免数组容量的扩张。当我们可预知要保存的元素的多少时,要在构造ArrayList实例时,就指定其容量,以避免数组扩容的发生。
extends E> c) 用一个ICollection对象来构造,并将该集合的元素添加到ArrayList public ArrayList(int initialCapacity) 用指定的大小来初始化内部的数组...; } private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = { }; 可以看出它的默认数组为长度为0。...: ** 向数组中添加第一个元素时,数组容量为10.** ** 向数组中添加到第10个元素时,数组容量仍为10.** ** 向数组中添加到第11个元素时,数组容量扩为15.** **... 向数组中添加到第16个元素时,数组容量扩为22.** 每次扩容都是通过Arrays.copyOf(elementData, newCapacity) 这样的方式实现的。...** 对比和总结:** 本文介绍了 ArrayList动态扩容的全过程。如果通过无参构造的话,初始数组容量为0,当真正对数组进行添加时,才真正分配容量。
当我们new -个空参构造时系统调用了EmptyArray.OBJECT 属性, EmptyArray仅 仅是一个系统的类库,该类源码如下: public final class EmptyArray...new -个空参ArrayList 的时候,系统内部使用了-个new Object[0]数组。...HashTable是线程安全的一个集合,不允许null值作为一个key值或者Value值; HashTable是sychronize,多个线程访问时不需要自己为它的方法实现同步,而HashMap在被多个线程访问的时候需要自己为它的方法实现同步...ArrayList和Vector使用了数组的实现,可以认为ArrayList或者Vector封装了对内部数组的操作,比如向数组中添加,删除,插入新的元素或者数据的扩展和重定向。...在JDK的实现中,无论LikedList是否为空,链表内部都有一个header表项,它既表示链表的开始,也表示链表的结尾。
这种实现方式,存在的问题有两个: 向集合中添加对象元素的时候,没有对元素的类型进行检查,也就是说,我们往集合中添加任意对象,编译器都不会报错。...当我们向rawArrayList 添加元素的时候 rawArrayList.add(0, "a"); 就限定其元素类型只能为String,那么在后面的获取元素的时候,自动强制转型为String 呢?...add元素错误信息 这通常会让我们感到困惑:为什么Number的对象可以由Integer实例化,而ArrayList的对象却不能由ArrayList实例化?...extends Number> list2 = new ArrayList(); 但是这里不能向list1、list2添加除null以外的任意对象。...Java为了保护其类型一致,禁止向List添加任意对象,不过可以添加空对象null。 ? 禁止向List<?
解析: 当在 ArrayList 中增加一个对象时 Java 会去检查 Arraylist 以确保已存在的数组中有足够的容量来存储这个新对象,如果没有足够容量就新建一个长度更长的数组(原来的1.5倍),...下面代码展示为 Java 1.8 中通过 ArrayList.add 方法添加元素时,内部会自动扩容,扩容流程如下: //确保容量够用,内部会尝试扩容,如果需要 ensureCapacityInternal...% Entry[].length; return Entry[index]; 当我们通过 put 向 HashMap 添加多个元素时会遇到两个 key 通过hash % Entry[].length计算得到相同...当我们通过 get 从 HashMap 获取元素时首先会定位到数组元素,接着再遍历该元素处的链表获取真实元素。...解析: ListIterator 有 add() 方法,可以向 List 中添加对象,而 Iterator 不能。
在每次添加新的元素时,ArrayList都会检查是否需要进行扩容操作,扩容操作带来数据向新数组的重新拷贝,所以如果我们知道具体业务数据量,在构造ArrayList时可以给ArrayList指定一个初始容量...为java关键字,为变量修饰符,如果用transient声明一个实例变量,当对象存储时,它的值不需要维持。Java的serialization提供了一种持久化对象实例的机制。...当持久化对象时,可能有一个特殊的对象数据成员,我们不想用serialization机制来保存它。为了在一个特定对象的一个域上关闭serialization,可以在这个域前加上关键字transient。...2.2、构造函数 ArrayList提供了三个构造函数: ArrayList():默认构造函数,提供初始容量为10的空列表。...上面为Entry对象的源代码,Entry为LinkedList的内部类,它定义了存储的元素。该元素的前一个元素、后一个元素,这是典型的双向链表定义方式。
当真正对数组进行添加元素操作时,才真正分配容量。即向数组中添加第一个元素时,数组容量扩为 10。下面在我们分析 ArrayList 扩容时会讲到这一点内容!...补充:JDK7 new无参构造的ArrayList对象时,直接创建了长度是10的Object[]数组elementData 。...add 进第 1 个元素到 ArrayList 时,elementData.length 为 0 (因为还是一个空的 list),因为执行了 ensureCapacityInternal() 方法 ,...7)ArrayList 实际上是通过一个数组去保存数据的。当我们使用无参构造函数构造ArrayList时,则ArrayList的默认容量大小是10。...Object[] EMPTY_ELEMENTDATA = {}; 用于创建默认大小ArrayList对象的空数组: private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA
大家好,又见面了,我是你们的朋友全栈君。 Java集合面试题 Java 集合框架的基础接口有哪些? Collection ,为集合层级的根接口。一个集合代表一组对象,这些对象即为它的元素。...主要结论如下: 如果通过无参构造的话,初始数组容量为 0 ,当真正对数组进行添加时,才真正分配容量。每次按照 1.5 倍(位运算)的比率通过 copeOf 的方式扩容。...HashSet 是用一个 hash 表来实现的,因此,它的元素是无序的。添加,删除和 HashSet 包括的方法的持续时间复杂度是 O(1) 。...基于你的 collection 的大小,也许向 HashMap 中添加元素会更快,再将 HashMap 换为 TreeMap 进行有序 key 的遍历。...当我们给 #put(key, value) 方法传递键和值时,我们先对键调用 #hashCode() 方法,返回的 hashCode 用于找到 bucket 位置来储存 Entry 对象。 ?
2)该类封装了一个动态再分配的Object[]数组,每一个类对象都有一个capacity属性,表示它们所封装的Object[]数组的长度,当向ArrayList中添加元素时,该属性值会自动增加。 ...3)ArrayList的用法和Vector向类似,但是Vector是一个较老的集合,具有很多缺点,不建议使用。 ...ArrayList的数据结构是: ? 说明:底层的数据结构就是数组,数组元素类型为Object类型,即可以存放所有类型数据。我们对ArrayList类的实例的所有的操作底层都是基于数组的。...当我们调用add方法时,实际上的函数调用如下: ? 说明:程序调用add,实际上还会进行一系列调用,可能会调用到grow,grow可能会调用hugeCapacity。 ...型构造函数,那么elementData被初始化为大小为6的Object数组,在调用add(8)方法时,具体的步骤如下: ?
ArrayList很好地帮我们解决了这个问题,当我们需要一个能根据包含元素的多少来动态调整大小的数组时,那么ArrayList正是我们所需要的。...) 当我们插入了比较多的元素,导致ArrayList快要装满时,它会自动增长容量。...若要想避免这种开销,在知道大概会容纳多少数据时,我们可以在构造时指定好它的大小以尽量避免它自动增长的发生;我们也可以调用ensureCapacity方法来增加ArrayList对象的容量到我们指定的大小...中允许出现null元素,所以在遍历的时候,如果为对象,获取对象属性的时候要先判断遍历出来的对象是否为null,这样才可以避免空指针异常。...只有当我们需要减少在列表中间添加或删除元素操作的代价时,可以考虑使用LinkedList。
// 任何空的ArrayList 将被扩展到10当(第一次添加元素时) // 注意是通过transient修饰 transient Object[] elementData; //...* 构造一个初始容量为10的空列表。...ArrayList的无参构造,其实默认是空数组,我们上面说的初始化容量默认为10,是当我们用无参构造函数后,第一次向ArrayList添加元素时扩容的默认大小。...删除元素是通过System.arraycopy移动数组覆盖元素来实现的 ArrayList添加元素时没有校验null值,所以删除null值时是特殊处理的 ArrayList通过对象删除时判断相等是通过equals...判断,所以我们在储存自定义对象是要注意对equals进行重写 通过源码我们可以看出在使用ArrayList时我们要尽量避免大量的随机删除,因为删除元素会导致元素拷贝(尤其是大元素),这是非常消耗性能的一件事
non-private to simplify nested class access 我想大家一定对这里出现的transient关键字很疑惑,我们都知道ArrayList对象是可序列化的,但这里为什么要用...实际上就是一个共享的空的Object数组对象。...[] EMPTY_ELEMENTDATA = {}; 上述代码很容易理解,如果用户指定的初始化容量大于0,就new一个相应大小的数组,如果指定的大小为0,就复制为共享的那个空的Object数组对象。...然后根据这个array的大小进行判断,如果不为0,就调用Arrays的copyOf的方法,复制到Object数组中,完成初始化,如果为0,就直接初始化为空的Object数组。...ArrayList是如何动态增长 当我们像一个ArrayList中添加数组的时候,首先会先检查数组中是不是有足够的空间来存储这个新添加的元素。如果有的话,那就什么都不用做,直接添加。
:在编写程序的时候,不会将其他非导出类型的对象添加到容器中。...三 List 数组存储多个对象的原因是它提前声明了能存储多少对象。那容器又是如何实现存储不定多对象的呢?...当使用无参构造函数时数组长度默认为空,当向ArrayList加入对象时,会调用一个方法来判断数组是否能放下这个对象。...当数组为空时设置数组长度为10并申请相应大小空间,当数组已满时,最少重新申请原数组大小1.5倍的空间(除非达到int类型最大值-8)。而在LinkedList中却没有采用这种方式,而是采用链表方式。...当我在ArrayList构造方法中设置数组初始大小1000万时,ArrayLIst添加数据的速度慢了下来,降到5000毫秒左右,所以一般情况下不需要优化。 总结 简单容器类图: ? ?
领取专属 10元无门槛券
手把手带您无忧上云