java集合之深入分析ArrayList
ArrayList特点:
ArrayList方法实现:
扩容方法的实现:
源码:
private void ensureCapacityInternal(int minCapacity) {
//如果数组为默认大小,则扩大的容量为minCapacity和默认值两个值的较大者
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
}
ensureExplicitCapacity(minCapacity);
}
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
//如果要扩大的容量比当前的数组长度大,则对数组进行扩容
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
/**
* Increases the capacity to ensure that it can hold at least the
* number of elements specified by the minimum capacity argument.
*
* @param minCapacity the desired minimum capacity
*/
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//增加的容量为原来大小的一半
int newCapacity = oldCapacity + (oldCapacity >> 1);
//如果增加了一半的容量还比要扩容的数量小,则新数组的大小为要扩容的数量
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果新数组的大小大于Integer.MAX_VALUE - 8,则进行判断
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);
}
private static int hugeCapacity(int minCapacity) {
//如果minCapacity < 0,则容量值溢出
if (minCapacity < 0) // overflow
throw new OutOfMemoryError();
return (minCapacity > MAX_ARRAY_SIZE) ?
Integer.MAX_VALUE :
MAX_ARRAY_SIZE;//Integer.MAX_VALUE - 8
}
clone方法分析:
ArrayList中的clone()方法为浅克隆,克隆后的集合对象与原有的集合对象不是同一个对象(即,指向不同的内存空间),但是它们集合元素引用的对象都是相同的。
源码:
public Object clone() {
try {
ArrayList<?> v = (ArrayList<?>) super.clone();
//重新分配了一个链表,但是里面的元素是复制的引用(浅克隆)
v.elementData = Arrays.copyOf(elementData, size);
v.modCount = 0;
return v;
} catch (CloneNotSupportedException e) {
// this shouldn't happen, since we are Cloneable
throw new InternalError(e);
}
}
示例程序:
ArrayList<String> list = new ArrayList<>();
//这样加入集合中时,引用的对象在常量池中
// list.add("dongfangbubai");
// String string = "dongfangbubai";
////这样加入集合中时,引用的对象堆中
String string = new String("dongfangbubai");
list.add(string);
list.add("shangshanruoshui"); ArrayList listClone = (ArrayList) list.clone();
System.out.println(listClone); String content = "dongfangbubai"; System.out.println(list.get(0).equals(content));
System.out.println(list.get(0) == content);
//克隆前后两个集合对应的元素所引用的都是同一个对象,true
System.out.println(list.get(0) == listClone.get(0));
//克隆前后两个集合是不同的集合,false
System.out.println(list == listClone);
ArrayList迭代时用迭代器只能一次删除一个元素(在一个迭代循环里),否则会出现java.lang.IllegalStateException异常。从源码可以看出这一点。
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
//进行一次删除操作时,随即就把lastRet置为一,每次迭代时就把迭代的元素索引赋个给astRet
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 数据结构发生改变,和fail-fast机制有关,在使用迭代器过程中,只能通过迭代器的方法(比如迭代器中add,remove等),修改List的数据结构, // 如果使用List的方法(比如List中的add,remove等),修改List的数据结构,会抛出ConcurrentModificationException
fail-fast机制的实现
fail-fast机制也叫作”快速失败”机制,是java集合中的一种错误检测机制。
在对集合进行迭代过程中,除了迭代器可以对集合进行数据结构上进行修改(迭代器进行结构修改时不会增加modCount值),其他的对集合的数据结构进行修改,都会抛出ConcurrentModificationException错误。
这里,所谓的进行数据结构上进行修改,是指对存储的对象,进行add,set,remove操作,进而对数据发生改变。
ArrayList中,有个modCount的变量,每次进行add,set,remove等操作,都会执行modCount++。
在获取ArrayList的迭代器时,会将ArrayList中的modCount保存在迭代中,
每次执行add,set,remove等操作,都会执行一次检查,调用checkForComodification方法,对modCount进行比较。
如果迭代器中的modCount和List中的modCount不同,则抛出ConcurrentModificationException
源码:源码中modCount在list中,
expectedModCount是在迭代时传入的modCount值,若迭代过程中list结构改变时,modCount会增加,以此迭代器1来判断迭代时list是否变化。
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
ArrayList与vector比较:
java集合之深入分析ArrayList的更多相关文章
- Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例
java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...
- java集合系列之ArrayList源码分析
java集合系列之ArrayList源码分析(基于jdk1.8) ArrayList简介 ArrayList时List接口的一个非常重要的实现子类,它的底层是通过动态数组实现的,因此它具备查询速度快, ...
- Java集合框架之ArrayList浅析
Java集合框架之ArrayList浅析 一.ArrayList综述: 位于java.util包下的ArrayList是java集合框架的重要成员,它就是传说中的动态数组,用MSDN中的说法,就是Ar ...
- 【Java集合系列】---ArrayList
开篇前言--ArrayList中的基本方法 前面的博文中,小编主要简单介绍java集合的总体架构,在接下来的博文中,小编将详细介绍里面的各个类,通过demo.对比,来对java集合类进行更加深入的理解 ...
- java集合系列之三(ArrayList)
上一章,我们学习了Collection的架构.这一章开始,我们对Collection的具体实现类进行讲解:首先,讲解List,而List中ArrayList又最为常用.因此,本章我们讲解ArrayLi ...
- java集合框架03——ArrayList和源码分析
最近忙着替公司招人好久没写了,荒废了不好意思. 上一章学习了Collection的架构,并阅读了部分源码,这一章开始,我们将对Collection的具体实现进行详细学习.首先学习List.而Array ...
- Java——集合框架之ArrayList,LinkedList,迭代器Iterator
概述--集合框架 Java语言的设计者对常用的数据结构和算法做了一些规范(接口)和实现(具体实现接口的类).所有抽象出来的数据结构和操作(算法)统称为Java集合框架(Java Collection ...
- Java集合框架(一)-ArrayList
大佬理解->Java集合之ArrayList 1.ArrayList的特点 存放的元素有序 元素不唯一(可以重复) 随机访问快 插入删除元素慢 非线程安全 2.底层实现 底层初始化,使用一个Ob ...
- java集合 collection-list-ArrayList 去除ArrayList集合中的重复元素。
import java.util.*; /* 去除ArrayList集合中的重复元素. */ class ArrayListTest { public static void sop(Object o ...
随机推荐
- [leetcode-667-Beautiful Arrangement II]
Given two integers n and k, you need to construct a list which contains n different positive integer ...
- 词频统计 SPEC 20170914 1 1 1 1 1
功能1 小文件输入,为表明程序能跑,结果真实而不是迫害老五,请他亲自键盘在控制台下输入命令. #include<stdio.h> #include<string.h> #inc ...
- TCP系列07—连接管理—6、TCP连接管理的状态机
经过前面对TCP连接管理的介绍,我们本小节通过TCP连接管理的状态机来总结一下看看TCP连接的状态变化 一.TCP状态机整体状态转换图(截取自第二版TCPIP详解) 二.TCP连接建立 ...
- 原生js 自定义confirm
本文参考博客园另一篇文章:https://www.cnblogs.com/hzj680539/p/5374052.html,在此感谢. 在实际开发当中,考虑到原生js组件,包括alert.confir ...
- Linux服务器记录并查询历史操作记录
Linux服务器在使用过程中,经常会有除自己之外的其他人员使用.并不是每个人都对Linux服务器特别熟悉,难免会有一些操作导致服务器报错. 因此,监控Linux服务器的操作并记录下来,是非常有必要的! ...
- AMH面板命令操作大全
LNMP面板 - AMH 命令使用nginx篇 » SSH Nginx1) 有步骤提示操作: ssh执行命令: amh nginx然后选择对应选项进行操作. 2) 或直接操作: 启动Nginx: am ...
- java 基础--数组--004
1,数组定义格式 String[] aa; String aa[];2,二位数组的定义格式1 String aa[][] = new String[m][n]; String[] aa[] = new ...
- Angular-Cli中引用第三方库
最近在学习angular(AngularJS 2),根据教程使用angular-cli新建项目, 然而在添加JQuery和Bootstrap第三方库时遇到了问题... 初试 我最初的想法是直接将相对路 ...
- 三次握手 四次握手 与socket函数的关系
“一切皆Socket!” 话虽些许夸张,但是事实也是,现在的网络编程几乎都是用的socket. ——有感于实际编程和开源项目研究. 我们深谙信息交流的价值,那网络中进程之间如何通信,如我们每天打开浏览 ...
- 一日一句 SQL [持续更新] MySQL + Oracle
1 . group by 和 having字句: group by是根据列值对数据进行分组, having子句用于对分组的数据进行过滤. [ having 针对的对象是分好的组] eg: employ ...