java arraylist 实现原理_Java进阶--深入理解ArrayList实现原理
编辑推荐:
文章主要介绍ArrayList的继承关系,ArrayList的方法使用和源码解析,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小,希望对您的学习有所帮助。
本文来自于csdn,由火龙果软件Delores编辑、推荐。
ArrayList简介
ArrayList就是动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了动态的增加和减少元素,实现了Collection和List接口,可以灵活的设置数组的大小。要注意的是ArrayList并不是线程安全的,因此一般建议在单线程中使用ArrayList。
ArrayList的继承关系
public class
ArrayList
extends AbstractList
implements List,
RandomAccess,Cloneable,Serializable
由上可知ArrayList继承AbstractList 并且实现了List和RandomAccess,Cloneable, Serializable接口。
ArrayList的方法使用和源码解析
①构造方法
//1-----------------------
public ArrayList() {
this(10);
//调用ArrayList(10)
默认初始化一个大小为10的object数组。
}
//2-------------------------
public ArrayList
(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException
("Illegal
Capacity: "+
initialCapacity);
//如果用户初始化大小小于0抛异常,
否则新建一个用户初始值大小的object数组。
this.elementData =
new Object[initialCapacity];
}
//3--------------------------
public ArrayList
(Collection< extends E> c) {
elementData = c.toArray();
size = elementData.length;
// 当c.toArray返回的
不是object类型的数组时,进行下面转化。
if (elementData.getClass()
!= Object[].class)
elementData = Arrays.copyOf
(elementData, size,
Object[].class);
}
由上面三种构造方法可知,默认情况下使用ArrayList会生成一个大小为10的Object类型的数组。也可以调用ArrayList(int initialCapacity) 来初始化Object数组的大小。并且用户可以往ArrayList中传入一个容器只要这个容器是Collection类型的。调用ArrayList(Collection< extends E > c)接口的时候会将容器数组化处理并将这个数组值赋给Object数组。
实例:
public static
void main
(String[] args) {
ArrayList list_2=new
ArrayList(20);
//list_2中添加元素
for(int i=0;i<10;i++)
list_2.add(i);
ArrayList list_3=new
ArrayList(list_2);
//输出list_2中元素
for(Integer a:list_2)
System.out.print(a+" ");
//输出list_3中元素
for(Integer a:list_3)
System.out.print(a+" ");
}
//输出
/*
list_2 : 0 1 2 3 4 5 6 7 8 9
-----------------------
list_3 : 0 1 2 3 4 5 6 7 8 9
*/
②indexOf(Object o)方法
功能:查找某个元素在ArrayList中第一次出现的位置。
public int indexOf(Object
o) {
//ArrayList中的元素可以为null,
如果为null返回null的下标
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
//如果没有找到对应的元素返回-1。
return -1;
}
对于indexof方法做几点说明:ArrayList中可以存放null元素,indexof是返回elementData数组中值相同的首个元素的下标,indexof中比较方法是equals而equals是比较元素的值,因此必须对null单独查找。如果未找到该元素则返回-1 。
public static
void main
(String[] args) {
ArrayList
list=new ArrayList();
list.add(1);
list.add(2);
list.add(null);
list.add(2);
list.add(3);
System.out.println
("null: "+list.indexOf(null));
System.out.println
("-------------------------");
System.out.println
("2: "+list.indexOf(2));
System.out.println
("-------------------------");
System.out.println
("4: "+list.indexOf(4));
}
//输出
/*
null: 2
-------------------------
2: 1
-------------------------
4: -1
*/
③lastIndexOf(Object o)方法
功能:查找某个元素在ArrayList中最后出现的位置。
public int lastIndexOf
(Object
o) {
if (o == null) {
//如果o为null从后往
前找到第一个为null的下标
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
//从后往前找到第一个值为o的下标
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
上面代码做几点说明:lastIndexOf(Object o)在ArrayList中从后往前找到第一个跟要查找值相同的元素的下标,因为是按值查找所以对于 null 要单独查找。如果未找到则返回-1;
④get(int index)方法
功能:返回ArrayList中指定下标为index的元素。
public E get(int
index) {
//检查index的值是否大于ArrayList的大小
rangeCheck(index);
//返回index下标的元素
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
//这里值检查index >= size的情况,
因为index<0时会自动抛出异常,
所以并未检查index<0的情况。
private void rangeCheck
(int index) {
if (index >= size)
throw new IndexOutOfBoundsException
(outOfBoundsMsg(index));
}
对上面代码做几点说明:上面代码中只检查了index>=size的情况,在index< 0的情况下也会抛出异常,只是这个异常是由系统抛出的。index >=size要检查的原因是有可能数组的大小大于index,然而有效里面的元素< index这时不抛异常就会返回无效值。举个例子ArrayList的初始化大小为10,现在往里面放5个元素,如果index >=5时,应该要抛出异常,而不是返回 null。因为null 是可以主动放在ArrayList中的。
⑤set(int index, E element)方法
功能:将element放到ArrayList下标为index的位置,如果index< 0或index >=size 抛异常,set(int index, E element)只能覆盖ArrayList中原来的元素,返回值为被覆盖的元素。
//1
public E set(int index, E element) {
//检查index是否小于size,如果不是抛异常
rangeCheck(index);
E oldValue = elementData(index);
elementData[index] = element;
//覆盖ArrayList中index上的元素。
return oldValue;
//返回被覆盖的元素。
}
//2
private void rangeCheck
(int index) {
if (index >= size)
throw new IndexOutOfBoundsException
(outOfBoundsMsg(index));
}
⑥add(E e)方法
功能:往ArrayList中添加元素。
//1-----------------------
public boolean add(E e) {
ensureCapacityInternal(size + 1);
// 加入元素前检查数组的容量是否足够
elementData[size++] = e;
return true;
}
//2-----------------------
private void ensureCapacityInternal
(int minCapacity)
{
modCount++;
// 如果添加元素后大于
当前数组的长度,则进行扩容
if (minCapacity -
elementData.length > 0)
grow(minCapacity);
}
//3-----------------------
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
//将数组的长度增加原来数组的一半。
int newCapacity = oldCapacity +
(oldCapacity >>
1);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
//如果扩充一半后仍然不够,则newCapacity= minCapacity;minCapacity实际元素的个数。
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
//数组最大位2^32
// minCapacity is usually close to size,
so this
is a win:
elementData = Arrays.copyOf
(elementData, newCapacity);
}
add方法比较复杂,涉及到扩充数组容量的问题。其中要弄清楚size和elementData.length的区别,size指的是数组中存放元素的个数,elementData.length表示数组的长度,当new一个ArrayList系统默认产生一个长度为10的elementData数组,elementData.length=10,但是由于elementData中还未放任何元素所有size=0。如果加入元素后数组大小不够会先进行扩容,每次扩容都将数组大小增大一半比如数组大小为10一次扩容后的大小为10+5=10;ArrayList的最大长度为 2^32 .
⑦add(int index, E element)方法
功能:往ArrayList指定index上添加元素,添加元素后ArrayList的大小增1。index及以后的元素都会向后移一位。 //1-------------------------
public void add
(int index, E element) {
rangeCheckForAdd(index);
//检查index的值是否
在0到size之间,可以为size。
ensureCapacityInternal(size + 1);
// 看elementData的长度是否足够,
不够扩容
//将elementData从index
开始后面的元素往后移一位。
System.arraycopy(elementData,
index, elementData,
index + 1,
size - index);
elementData[index] = element;
size++;
}
//2-------------------------
private void rangeCheckForAdd
(int index) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException
(outOfBoundsMsg(index));
}
//3-------------------------
private void ensureCapacityInternal
(int minCapacity)
{
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
add(int index, E element)往指定index中加入元素,加入元素之前先检查数组的大小,如果小了在原来基础上增大一半,将ArrayList只能怪index及以后的元素往后移一位,将element放到index位置。
⑧remove(int index)方法
功能:删除ArrayList指定位置的元素。
public E remove(int
index) {
rangeCheck(index);
//如果index>=size抛出异常
modCount++;
E oldValue = elementData(index);
//获取删除元素的值
int numMoved = size - index - 1;
//将index后面所有的元素往前移一位。
if (numMoved > 0)
System.arraycopy(elementData,
index+1, elementData,
index,
numMoved);
elementData[--size] = null;
// Let gc do its work
//返回要删除的原数。
return oldValue;
}
⑨remove(Object o)方法
功能:删除ArrayList中值为o的元素
public boolean
remove
(Object o) {
if (o == null) {
for (int index = 0;
index < size; index++)
if (elementData[index]==null){
fastRemove(index);
return true;
}
} else {
for (int index = 0;
index < size; index++)
if (o.equals
(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
java arraylist 实现原理_Java进阶--深入理解ArrayList实现原理相关推荐
- java 编程原理_Java网络编程 -- 网络编程基础原理
Hello,今天记录下 Java网络编程 --> 网络编程基础原理. 一起学习,一起进步.继续沉淀,慢慢强大.希望这文章对您有帮助.若有写的不好的地方,欢迎评论给建议哈! 初写博客不久,我是杨展 ...
- Java设计流程执行器_Java进阶面试精选系列:SpringMVC+SpringBoot+Hibernate+Mybatis+设计模式...
小编精心收集:为金三银四准备,以下面试题先过一遍,为即将到了的面试做好准备,也过一遍基础知识点. 一.Spring/Spring MVC 1.为什么要使用 spring? 2.解释一下什么是 aop? ...
- java同步方法完成案例_Java同步代码块和同步方法原理与应用案例详解
本文实例讲述了java同步代码块和同步方法.分享给大家供大家参考,具体如下: 一 点睛 所谓原子性WOmoad:一段代码要么执行,要么不执行,不存在执行一部分被中断的情况.言外之意是这段代码就像原子一 ...
- java session原理_java web开发—session的工作原理总结
session的工作原理总结 一.什么是session session是一次浏览器和服务器交互的会话,在jsp中,作为一个内置对象存在.我的理解,就是当用户打开网页时,程序会在浏览器中开辟一段空间来存 ...
- java static 变量共享_java中如何理解多个对象共享同一个静态成员变量?
展开全部 要理解这个问题首先要知道一点,就是java的静态成62616964757a686964616fe59b9ee7ad9431333433643133员变量是有一个独立的存储空间的. 假设一个类 ...
- java 中适配器原理_Java经典设计模式中关于适配器模式原理以及用法详解
这篇文章主要介绍了Java经典设计模式之适配器模式,简单说明了适配器模式的概念.原理,并结合实例形式分析了java适配器模式的用法与相关注意事项,需要的朋友可以参考下 本文实例讲述了Java经典设计模 ...
- java 迭代器的原理_Java集合框架迭代器Iterator实现原理解析
使用循环遍历集合 普通for循环 for(int i=0;i<10;i++){} 增强for循环 for(String str:list){} 什么是迭代器Iterator Iterator是J ...
- java 同步块原理_Java同步代码块和同步方法原理与应用案例详解
Java同步代码块和同步方法原理与应用案例详解 发布于 2020-8-7| 复制链接 摘记: 本文实例讲述了Java同步代码块和同步方法.分享给大家供大家参考,具体如下:一 点睛所谓原子性:一段代码要 ...
- 结构化分析与面向对象的区别_JAVA进阶 深入理解面向对象
一.结构化程序设计与面向对象 1. 概述 早期的编程语言如:C.Basic.Pascal等都是结构化编程语言.结构化程序设计的核心思想就是程序的开发采用自上而下的设计(称为瀑布模式).对于大型的应用来 ...
最新文章
- 【leetcode75】Intersection of Two Arrays(数组的交集)
- Object-C 入门介绍
- Velocity语法使用总结
- 计算二叉树叶子节点的数目
- 虚拟机上安装完成redhat后无法上网和Xshell无法连接虚拟机的问题
- 2017年苹果公司开发者账号申请-公司邓白氏编码
- 2.18比赛(T2,T3留坑)
- 检验多重共线性matlab_异方差太难?检验通不过?横截面分析难题的十大暴击!...
- 80 后技术人的中年危机
- 公钥和私钥的作用和区别
- 20165309 《网络对抗技术》实验二:后门原理与实践
- JavaWeb——新闻管理系统(Jsp+Servlet)
- kindeditor 编辑器手机访问默认为HTML编辑
- android5.0电话录音,用Xpose完美实现电话录音,支持android 8.1.0
- 服务器显卡驱动重装系统,windows7旗舰版系统重装显卡驱动的方法
- gnuradio3.8.2的安装步骤
- 解决错误Establishing SSL connection without server‘s identity verification is not recommended.
- matlab怎么求解二元高次方程,高次二元方程求解
- Jquery引用在线CDN公共资源库
- 项目实训第一周第三篇
热门文章
- 如何同时安装Office2003和Office2007!
- 《AngularJS实战》——3.1 模板中的过滤器
- jQuery 的 serializeArray()、serialize() 方法
- 0x80070002错误一例
- 软件项目开发无成熟框架套路之成本代价
- ScribeFireBlog 发的一篇在Cnblogs的日志
- K-means聚类自定义距离计算
- 荣发护肤护甲增强配方 Hair, Skin and Nails Plus 100 tablets
- Oracle+jsp+Servlet的员工表的简单增删改查
- 使用 JMeter 进行压力测试