java arraylist源码记录
1. ArrayList 实现了RandomAccess接口, RandomAccess接口用于标记是否可以随机访问
2. 继承了AbstractList类, 因此获取了modcount , modcount用于实现快速失败机制, 如果list有修改, 那么modcount自增
3. ArrayList不支持并发, 是非线程安全的
4. 支持存放null元素
5. 扩容, 每次都是原来大小的1.5倍
public void ensureCapacity(int minCapacity) {
//如果elementData不等于EMPTY_ELEMENTDATA(因为初始化时有可能等于), 那么minExpand为0或者DEFAULT_CAPACITY
//如果elementData不为空minExpand为0, 可以用这个来处理minCapacity为负数的情况
//如果elementData为空, 那么就是默认容量
int minExpand = (elementData != EMPTY_ELEMENTDATA)
// any size if real element table
? 0
// larger than default for empty table. It's already supposed to be
// at default size.
: DEFAULT_CAPACITY;
//如果最小容量大于minExpand, 那么进行明确扩容
if (minCapacity > minExpand) {
ensureExplicitCapacity(minCapacity);
}
}
//已确定扩容minCapacity
private void ensureExplicitCapacity(int minCapacity) {
modCount++; //修改次数加1
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//newCapacity为oldCapacity的1.5倍, 这里有可能会溢出为-1
int newCapacity = oldCapacity + (oldCapacity >> 1);
....
}
6. lastIndexOf, contains, indexOf方法用于查找, 时间复杂度均为O(N), 使用对象的equals方法进行比较
7. clone() 方法为深复制, 所谓深复制和浅复制的区别在于复制内部引用对象时的不同, 深复制会将原来的对象重新clone一份, 让复制对象的引用指向新对象, 而浅复制仅仅复制引用, 仍指向原来的对象. java Object中的clone方法为浅复制
8. set() 和 get() 为O(1)的时间复杂度
9. 调用ensureCapacityInternal(int) 会使modCount+1. ArrayList中的添加元素都会调用这个函数 ,例如add(object)和add(int,Object)
10. add(Object) 和add(int,Object)的时间复杂度为O(N), 因为底层数组的复制移动
11. remove(int)方法也会使modCount+1, 时间复杂度为O(N) , 同时内部使用elementData[--size] = null;用来防止内存泄漏, 以便gc释放内存
12. remove(Object) 使用了fastRemove非法, fastRemove如果未找到删除元素, 那么modCount是不会变的, 反之modCount+1 , 之所以fastRemove称之为fast是因为使用了System.arrayCopy进行元素移动, System.arrayCopy是一个native方法, 可以躲避java访问数组时的下标检查.
13. clear方法, modCount+1
14. addAll(...) 都会调用ensureCapacityInternal方法, 从而使modCount+1, O(N)的时间复杂度
15. removeAll(object)//补集和retainAll(object)//交集 都可以使用batchRemove方法, O(N^2)的时间复杂度, modCount+1.
16. 快速失败机制体现在容器的遍历中, Iterator会在对象初始化过程中保存当前容器的modCount, 并在每次遍历检查modCount, 如果两者不一致, 那么说明容器在遍历时被修改, 抛出ConcurrentModificationException.
private class Itr implements Iterator<E> {
int expectedModCount = modCount;
public E next() {
checkForComodification();
int i = cursor;
...
}
public void remove() {
...
checkForComodification();
...
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
java arraylist源码记录的更多相关文章
- Java ArrayList源码剖析
转自: Java ArrayList源码剖析 总体介绍 ArrayList实现了List接口,是顺序容器,即元素存放的数据与放进去的顺序相同,允许放入null元素,底层通过数组实现.除该类未实现同步外 ...
- Java ArrayList源码分析(有助于理解数据结构)
arraylist源码分析 1.数组介绍 数组是数据结构中很基本的结构,很多编程语言都内置数组,类似于数据结构中的线性表 在java中当创建数组时会在内存中划分出一块连续的内存,然后当有数据进入的时候 ...
- Java ArrayList源码分析(含扩容机制等重点问题分析)
写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...
- Java - ArrayList源码分析
java提高篇(二一)-----ArrayList 一.ArrayList概述 ArrayList是实现List接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 nul ...
- Java——ArrayList源码解析
以下针对JDK 1.8版本中的ArrayList进行分析. 概述 ArrayList基于List接口实现的大小可变的数组.其实现了所有可选的List操作,并且元素允许为任意类型,包括null元 ...
- Java|ArrayList源码分析|add()增加方法和grow()扩容方法
本文结构: 1.介绍特点 2.基本方法 3.重点源码分析 1.介绍特点 ArrayList: 是List的一个具体实现子类,是List接口的一个数组实现 (里面必定维护了一个数组). 默认初始容量10 ...
- java ArrayList源码分析(转载)
1.ArrayList是一个相对来说比较简单的数据结构,最重要的一点就是它的自动扩容,可以认为就是我们常说的“动态数组”. 来看一段简单的代码: 12345 ArrayList<String&g ...
- 【源码阅读】Java集合之一 - ArrayList源码深度解读
Java 源码阅读的第一步是Collection框架源码,这也是面试基础中的基础: 针对Collection的源码阅读写一个系列的文章,从ArrayList开始第一篇. ---@pdai JDK版本 ...
- Java集合源码分析(一)ArrayList
前言 在前面的学习集合中只是介绍了集合的相关用法,我们想要更深入的去了解集合那就要通过我们去分析它的源码来了解它.希望对集合有一个更进一步的理解! 既然是看源码那我们要怎么看一个类的源码呢?这里我推荐 ...
随机推荐
- Solr5.2.1+Zookeeper3.4.9分布式集群搭建
1.选取三台服务器 由于机器比较少,现将zookeeper和solr都部署在以下三台机器上.(以下操作都是在172.16.20.101主节点上进行的哦) 172.16.20.101 主节点 172.1 ...
- 共享内存之——mmap内存映射
共享内存允许两个或多个进程共享一给定的存储区,因为数据不需要来回复制,所以是最快的一种进程间通信机制.共享内存可以通过mmap()映射普通文件 (特殊情况下还可以采用匿名映射)机制实现,也可以通过sy ...
- AC日记——【模板】最小费用最大流 P3381
题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表 ...
- 2017 ACM-ICPC 北京区域赛记录
------------------------------------------------------------------------------ 出发日 拖着一个大箱子走是真的累. 下午三 ...
- 可能是全网最详细的express--middleware
写在前面 hello,小伙伴们,我是你们的pubdreamcc,本篇博文出至于我的GitHub仓库node学习教程资料,欢迎小伙伴们点赞和star,你们的点赞是我持续更新的动力. GitHub仓库地址 ...
- python生成器、迭代器、__call__、闭包简单说明
1.生成器 这种一边循环一边计算的机制,称为生成器:generator,最简单的方法是把生成式的[]改为(). >>> l=(x * x for x in range(1, 11) ...
- java布局(每个名字都是有意义的)
一.FlowLayout 1.流水布局:从左至右,排满换行 2.构造函数有三种: (1)FlowLayout() (2)FlowLayout(align) (3)FlowLayout(align, h ...
- Maven修改默认中央仓库
其实Maven的默认仓库是可以修改的.比如使用阿里云的镜像地址等. 修改步骤: 1.打开{M2_HOME}/conf/settings.xml文件,找到mirrors节点,修改如下代码: <mi ...
- DELPHI跨平台编译开关
DELPHI跨平台编译开关 DELPHI 现在是跨平台的开发工具,已经不仅仅针对WINDOWS OS. 跨平台的时候,一些WINDOWS特有的API或语法是不能用的,必须使用跨平台的新语法,要用编译开 ...
- Ubuntu -- 下如何查看CPU信息, 包括位数和多核信息
from: http://hi.baidu.com/sdusoul/blog/item/76f349508f74fb6e843524eb.html 查看当前操作系统内核信息# uname -a Lin ...