ArrayList内部实现原理

ArrayList内部实现原理

java

list

首先,我们new一个对象list集合

	List<String> list = new ArrayList<>();

我们知道对象的创建离不开构造方法,因此我们查看ArrayList源码的时候先看其构造方法

	private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
	transient Object[] elementData; // non-private to simplify nested class access

	public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }

通过源码我们发现在new ArrayList<>()的时候,其实质是获得一个Object[]数组;

因此ArrayList的本质就是一个数组

然后我们向元素中添加一个对象通过add()方法,并查看add的源码

	list.add("123");
	private int size;

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

在add方法中调用了一个方法ensureCapacityInternal()用来初始化容量

然后向数组的末尾添加了一个元素

接下来我们来看看这个ensureCapacityInternal()方法的内部是如何实现的

	private static final int DEFAULT_CAPACITY = 10;

	private void ensureCapacityInternal(int minCapacity) {
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }

        ensureExplicitCapacity(minCapacity);
    }

很显然在ArrayList被创建的时候执行了this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;,因此if语句是成立的,我们知道当我们第一次执行add("123")的时候size=0,因此该方法的参数是1。所以minCapacity=10

然后我们看ensureExplicitCapacity(minCapacity);这个方法的内部。

	protected transient int modCount = 0;

	private void ensureExplicitCapacity(int minCapacity) {
        modCount++;

        // overflow-conscious code
        if (minCapacity - elementData.length > 0)
            grow(minCapacity);
    }

因为elementData是一个null的对象数组,所以elementData.length=0,if条件成立执行grow(minCapacity)

	 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;

	private void grow(int minCapacity) {
        // overflow-conscious code
        int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);
        if (newCapacity - minCapacity < 0)
            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);
    }

因为minCapacity=0,所以newCapacity=0,导致if(newCapacity - minCapacity<0)成立,结果newCapacity = minCapacity;等于10;

MAX_ARRAY_SIZE= Integer.MAX_VALUE - 8;可以认为MAX_ARRAY_SIZE是一个无穷大的数,因此if (newCapacity - MAX_ARRAY_SIZE > 0)语句不成立,elementData = Arrays.copyOf(elementData, newCapacity);拷贝原数组到新数组,新数组长度为10;

当我们继续添加直到ArrayListsize=10,我们继续add第11个对象的时候if (minCapacity - elementData.length > 0)成立,

 		int oldCapacity = elementData.length;
        int newCapacity = oldCapacity + (oldCapacity >> 1);

因此,当ArrayList容量存满的时候,会扩容为原来的3/2倍

通过内部原理可知,对于ArrayList的每次操作,当需要扩容的时候,每次扩容为当前长度的1.5倍,但是每次操作集合都需要进行数组的拷贝,此过程消耗资源,所以如果对于经常对集合进行添加删除操作的时候,不建议使用ArrayList

ArrayList内部原理

时间: 2024-08-09 14:44:13

ArrayList内部实现原理的相关文章

[转] 浅谈 ArrayList 内部原理

转自:浅谈 ArrayList 内部原理 System.Collections.ArrayList 就是我们常说的动态数组,也是我们常用的 "数据类型" 之一.在 MSDN 上是这样表述的:使用大小可按需动态增加的数组实现 IList 接口.我来解释一下,就是:一个可以根据需要动态增加使用大小并可按照索引单独访问的对象的非泛型集合.一般人都认为 ArrayList 就是一个 "纯动态" 的数组,与 <数据结构> 中 "链表" 的原理一

LinkedList内部实现原理

LinkedList内部实现原理 java list 同ArrayList内部原理一样 我们先创建一个LinkedList对象LinkedList<String> li = new LinkedList<>();,然后查看其构造方法 transient Node<E> first; transient Node<E> last; public LinkedList() { } 比较尴尬的是在它的构造方法中什么也没有写.LinkedList的结构是**双向链表

ArrayList的实现原理--转

1. ArrayList概述: ArrayList是List接口的可变数组的实现.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小.   每个ArrayList实例都有一个容量,该容量是指用来存储列表元素的数组的大小.它总是至少等于列表的大小.随着向ArrayList中不断添加元素,其容量也自动增长.自动增长会带来数据向新数组的重新拷贝,因此,如果可预知数据量的多少,可在构造ArrayList时指定其容

KVO内部实现原理

// // ViewController.m // KVO内部实现原理 // // Created by sw on 15/4/13. // Copyright © 2015年 sw. All rights reserved. // #import "ViewController.h" #import "Person.h" @interface ViewController () @end @implementation ViewController - (void

Maven内部运行原理

原作者zlwen 原文链接 内部运行原理(二) maven至今还是Java编程语言构建的事实标准,大部分项目还在使用maven来进行构建,因此了解maven内部运行的原理对定位和分析问题还是很有裨益的.本篇文章主要介绍一些maven内部运行过程中的一些基本概念,相信看完后,对那么些刚刚接触maven的读者来说maven将不再陌生.??在具体分析项目构建的过程前,需要了解maven的一些基本概念,这些概念十分重要,请务必理解清楚后再看下文.基本概念主要有:POM,Lifecycle.这两个概念又会

关于SDWebimage的内部实现原理

SDWebimage的内部实现原理各路大神都已经剖析的很透彻了 我也来发一下希望大家共同讨论学习 1.入口 setImageWithURL:placeholderImage:options: 会先把 placeholderImage 显示,然后 SDWebImageManager 根据 URL 开始处理图片. 2.进入 SDWebImageManager-downloadWithURL:delegate:options:userInfo: 交给 SDImageCache 从缓存查找图片是否已经下

利用反射模拟一个spring的内部工作原理

这个简单的案例是实行了登录和注册的功能,没有链接数据库. 在bean中id 是唯一的,id和name的区别在于id不能用特殊字符而name可以用特殊字符,比如:/-\.... 1 package com.obtk.reflect; 2 3 public class Logon { 4 /** 5 * 帐号密码长度大于六位字符就成功,否则失败! 6 * */ 7 public String select(String name, String pass) { 8 if (name.length()

前端必读:浏览器内部工作原理

前端必读:浏览器内部工作原理 作者: Tali Garsiel  发布时间: 2012-02-09 14:32  阅读: 56974 次  推荐: 88   原文链接   [收藏] 目录 一.介绍 二.渲染引擎 三.解析与DOM树构建 四.渲染树构建 五.布局 六.绘制 七.动态变化 八.渲染引擎的线程 九.CSS2可视模型 英文原文:How Browsers Work: Behind the Scenes of Modern Web Browsers 一.介绍 浏览器可以被认为是使用最广泛的软

LINQ内部执行原理浅析

C#3.0 增加LINQ的特性 一.基本概念 LINQ,语言级集成查询(Language INtegrated Query) 经过了最近 20 年,面向对象编程技术( object-oriented (OO) programming technologies )在工业领域的应用已经进入了一个稳定的发展阶段.程序员现在都已经认同像类(classes).对象(objects).方法(methods)这样的语言特性.考察现在和下一代的技术,一个新的编程技术的重大挑战开始呈现出来,即面向对象技术诞生以来