jdk 1.8下 java ArrayList 添加元素解析

转载请注明http://www.cnblogs.com/majianming/p/8006452.html

有人问我,java ArrayList底层是怎么实现的?我就回答数组,他再问我,那它是怎么实现数组的添加的呢?我也不知道,就不敢回答了。

回来赶紧看了一下java实现,明确的是ArrayList底层的确是用数组实现的,但是怎么实现数组的扩容的呢?

简单来说,就是创建一个新的比原来大的数组,把原来所有的元素复制到新的数组,然后添加新的数组进去



先从无参构造函数开始,无参构造函数创建了一个容量为0的空数组(这里要注意,在jdk1.8时采用的是创建空数组,在1.7还是创建了一个容量为10的数组,源码见附录1,2,这里以1.8为例)

然后就可以开始调用add方法添加元素,这里先以public boolean add(E e)方法为例

  1. 计算最小容量:判断是不是第一次添加,准确来说是不是一个空数组。如果是一个空数组,那么设置初始化大小(即最小容量)为10,如果不是,那么在原来基础上大小+1。
  2. 判断是否需要扩容:判断最小容量是不是大于数组长度(至少大1),如果是,进行第3步。为什么有这个判断?是最小容量是数组可以存放的元素个数,而数组长度是实际上存放的个数,那么就会出现数组还没放满的情况,比如第二次添加时,数组容量为10(第一次初始化时设置为10),元素加上新增加的只有两个,是不需要进行第3,4步的
  3. 扩容计算:
    1. 取得已有元素的个数,准备设置新的容量为原来元素个数的1.5倍
    2. 将1中的新容量和最小容量相对比,取大的(所以初始化时原来元素的1.5倍为0小于最小容量10,设置为10)
    3. 将2中计算结果与Integer.MAX_VALUE - 8对比(为啥是-8 ,doc上是说明了一些虚拟机实现需要多存一些头信息,为了防止oom,其他没有说明,在stackoverflow上说明了为了存下数组的最大大小2,147,483,648所以需要(见附录3))还大,那就没办法了,只能设置为Integer.MAX_VALUE。也就是说正常情况下数组最大容量为下最大值减8,否则就是最大值。这个时候放不下那就只能抛异常了呗!
  4. 复制旧元素到新数组:上一步计算的只是一个值,没有对原来的进行修改,也没有创建新的数组。接下来使用Arrays.copyOf将原来数组的所有元素复制到新数组(以最小容量创建的),并返回
  5. 把添加的元素添加到新返回的数组最后,长度+1


附录

  1. jdk 1.7 ArrayList
  2. jdk 1.8 ArrayList
  3. 为什么-8


参考

Java中ArrayList源码浅析



设定

jdk:1.8_102

转载请注明http://www.cnblogs.com/majianming/p/8006452.html

时间: 2024-07-28 22:13:24

jdk 1.8下 java ArrayList 添加元素解析的相关文章

ubuntu下java环境变量配置

转自:http://blog.csdn.net/tenpage/article/details/7215810 如果是配置java环境,请参照这篇,更简单:在Ubuntu 12.04 LTS上安装JDK6 一. 解压安装jdk 在shell终端下进入jdk-6u14-linux-i586.bin文件所在目录, 执行命令 ./jdk-6u14-linux-i586.bin 这时会出现一段协议,连继敲回车,当询问是否同意的时候,输入yes,回车.之后会在当前目录下生成一个jdk1.6.0_14目录,

关于Java面试知识点解析——JVM基础篇

跳槽时时刻刻都在发生,但是我建议大家跳槽之前,先想清楚为什么要跳槽.切不可跟风,看到同事一个个都走了,自己也盲目的开始面试起来(期间也没有准备充分),到底是因为技术原因(影响自己的发展,偏移自己规划的轨迹),还是钱给少了,不受重视. 准备不充分的面试,完全是浪费时间,更是对自己的不负责(如果title很高,当我没说).今天给大家分享下 Java面试知识点解析--JVM基础篇 1)Java 是如何实现跨平台的? 注意:跨平台的是 Java 程序,而不是 JVM.JVM 是用 C/C++ 开发的,是

Java的开发平台JDK在Windows下的环境变量配置

http://blog.sina.com.cn/s/blog_76e84df301015edc.html JDK安装完成后,一般需要设置JAVA_HOME.CLASSPATH.PATH三个环境变量的值,以及测试JDK配置是否成功. 一.什么是用户变量?什么是系统变量? 答:用户变量是只能当前用户使用的变量,系统变量是系统下任何用户都可以使用的变量. 二.为什么需要配置环境变量? 答:我们知道,在系统的“运行”窗口中可以输入指定的命令运行相应的程序,如果在输入命令时没有指定完整的路径,系统将自动到

Windows 下 java(JDK)的安装和环境变量的配置

1.下载JDK安装包: http://www.oracle.com/technetwork/java/javaee/downloads/index-jsp-140710.html 2.安装JDK. 3.环境变量中新建: JAVA_HOME =D:\worksoft\Java\jdk1.6.0_20; 4.环境变量中新建: CLASSPATH = .;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar; 5.修改环境变量Path,在其后添加: %JAV

Linux(Ubuntu 16) 下Java开发环境的配置(一)------JDK的配置

前言: 本文介绍的是通用的安装方法,一般linux系统均可使用该方法安装.本文以Java8环境为例进行配置. 1.JDK的下载 进入java下载页(http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html ),下载java的JDK,选择"jdk-8u161-linux-i586.tar.gz"文件,下载到本地. 2.JDK的安装 因为usr/lib目录下的操作是需要管理员权限的

java ArrayList集合分析

一. ArrayList概述: 本文的源代码分析基于的JDK版本是1.8. ArrayList是基于数组实现的,是一个动态数组,其容量能自动增长,类似于C语言中的动态申请内存,动态增长内存. ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下可以考虑用Collections.synchronizedList(List l)函数返回一个线程安全的ArrayList类,也可以使用concurrent并发包下的CopyOnWriteArrayList类. ArrayList实现了Se

jdk集合常用方法分析之ArrayList&LinkedList&以及两者的对比分析

集合使用注意事项: 1.集合当中只能放置对象的引用,无法放置原生数据类型,我们需要使用原生数据类型的包装类才能加入到集合当中去(JDK5之后会进行自动的装箱和拆箱操作,表面上看集合中是可以直接放置原生数据类型进去,但实质上是进过自动装箱成对象操作的): 2.集合当中放置的都是Object类型,因此取出来的也是Object类型(可以放置任意类型的数据),那么必须要使用强制类型转换将其转换为真正的类型(放置进去的类型). ArrayList ArrayList常用方法: boolean add(E

java classLoader机制解析

类从被加载到虚拟机内存中开始,到卸装出内存为止,它的整个生命周期包括了:加载,连接(验证,准备,解析),初始化,使用和卸载七个阶段.其中验证.准备和解析三个部分称为连接,也就是说,一个Java类从字节代码到能够在JVM中被使用,需要经过加载.链接和初始化这三个步骤 .我们看一看Java虚拟机的体系结构. Java虚拟机的体系结构如下图所示: Java类加载的全过程,是加载.验证.准备.解析和初始化这五个阶段的过程.而加载阶段是类加载过程的一个阶段.在加载阶段,虚拟机需要完成以下三件事情: 通过一

JDK源码看Java域名解析

前言 在互联网中通信需要借助 IP 地址来定位到主机,而 IP 地址由很多数字组成,对于人类来说记住某些组合数字很困难,于是,为了方便大家记住某地址而引入主机名和域名. 早期的网络中的机器数量很少,能很方便地通过 hosts 文件来完成主机名称和 IP 地址的映射,这种方式需要用户自己维护网络上所有主机的映射关系.后来互联网迅猛发展起来,hosts 文件方式已经无法胜任,于是引入域名系统(DNS)来解决主机名称和 IP 地址的映射. 局域网中常用来表示 IP 地址的名称更多称为主机名,而互联网上