- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章Java集合框架ArrayList源码分析(一)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
ArrayList底层维护的是一个动态数组,每个ArrayList实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长.
ArrayList不是同步的(也就是说不是线程安全的),如果多个线程同时访问一个ArrayList实例,而其中至少一个线程从结构上修改了列表,那么它必须保持外部同步,在多线程环境下,可以使用Collections.synchronizedList方法声明一个线程安全的ArrayList,例如: List arraylist = Collections.synchronizedList(new ArrayList()); 下面通过ArrayList的源码来分析其原理。 1、ArrayList的构造方法:ArrayList提供了三种不同的构造方法 1) ArrayList(),构造一个初始容量为 10 的空列表。 2) ArrayList(int initialCapacity),构造一个具有指定初始容量的空列表。 3) ArrayList(Collection<? extends E> c),构造一个包含指定 collection 的元素的列表,这些元素是按照该 collection 的迭代器返回它们的顺序排列的.
源码如下: 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
private
transient
Object[] elementData;
public
ArrayList(
int
initialCapacity) {
super
();
if
(initialCapacity <
0
)
throw
new
IllegalArgumentException(
"Illegal Capacity: "
+ initialCapacity);
this
.elementData =
new
Object[initialCapacity];
//生成一个长度为10的Object类型的数组
}
public
ArrayList() {
this
(
10
);
//调用ArrayList(int i)
}<br><br>
public
ArrayList(Collection<?
extends
E> c) {
elementData = c.toArray();
//返回包含此 collection 中所有元素的数组
size = elementData.length;
// c.toArray might (incorrectly) not return Object[] (see 6260652)
if
(elementData.getClass() != Object[].
class
)
elementData = Arrays.copyOf(elementData, size, Object[].
class
);
//复制指定的数组,返回包含相同元素和长度的Object类型的数组
}
|
当采用不带参数的构造方法ArrayList()生成一个集合对象时,其实是在底层调用ArrayList(int initialCapacity)这一构造方法生产一个长度为10的Object类型的数组。当采用带有集合类型参数的构造方法时,在底层生成一个包含相同的元素和长度的Object类型的数组。 。
2、add方法:ArrayList提供了两种添加元素的add方法 1) add(E e),将指定的元素添加到此列表的尾部。 2) add(int index, E e),将指定的元素插入此列表中的指定位置。向右移动当前位于该位置的元素(如果有)以及所有后续元素(将其索引加 1)private int size,
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
public
boolean
add(E e) {
ensureCapacity(size +
1
);
// 扩大数组容量
elementData[size++] = e;
//将元素e添加到下标为size的Object数组中,并且执行size++
return
true
;
}
public
void
add(
int
index, E element) {
if
(index > size || index <
0
)
//如果指定要插入的数组下标超过数组容量或者指定的下标小于0,抛异常
throw
new
IndexOutOfBoundsException(
"Index: "
+index+
", Size: "
+size);
ensureCapacity(size+
1
);
// 扩大数组容量
System.arraycopy(elementData, index, elementData, index +
1
,size - index);
//从指定源数组中复制一个数组,复制从指定的位置开始,到目标数组的指定位置结束。<br> // elementData --- 源数组 index --- 源数组中的起始位置 <br> // elementData --- 目标数组 index+1 --- 目标数组中的起始位置<br> // size - index --- 要复制的数组元素的数量
elementData[index] = element;
//将要添加的元素放到指定的数组下标处
size++;
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
public
void
ensureCapacity(
int
minCapacity) {
modCount++;
int
oldCapacity = elementData.length;
//原数组的容量
if
(minCapacity > oldCapacity) {
Object oldData[] = elementData;
int
newCapacity = (oldCapacity *
3
)/
2
+
1
;
//定义新数组的容量,为原数组容量的1.5倍+1
if
(newCapacity < minCapacity)
newCapacity = minCapacity;
// minCapacity is usually close to size, so this is a win:
elementData = Arrays.copyOf(elementData, newCapacity);
//复制指定的数组,返回新数组的容量为newCapacity
}
}
|
如果集合中添加的元素超过了10个,那么ArrayList底层会新生成一个数组,长度为原数组的1.5倍+1,并将原数组中的元素copy到新数组中,并且后续添加的元素都会放在新数组中,当新数组的长度无法容纳新添加的元素时,重复该过程。这就是集合添加元素的实现原理.
3、get方法: 1) get(int index),返回此列表中指定位置上的元素.
1
2
3
4
5
6
7
8
9
10
11
12
|
public
E get(
int
index) {
RangeCheck(index);
//检查传入的指定下标是否合法
return
(E) elementData[index];
//返回数组下标为index的数组元素
}
private
void
RangeCheck(
int
index) {
if
(index >= size)
//如果传入的下标大于或等于集合的容量,抛异常
throw
new
IndexOutOfBoundsException(
"Index: "
+index+
", Size: "
+size);
}
|
4、remove方法: 1) E remove(int index),移除此列表中指定位置上的元素。向左移动所有后续元素(将其索引减 1)。 2) boolean remove(Object o),移除此列表中首次出现的指定元素(如果存在)。如果列表不包含此元素,则列表不做改动,返回boolean值。 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
public
E remove(
int
index) {
RangeCheck(index);
//检查指定的下标是否合法
modCount++;
E oldValue = (E) elementData[index];
//获取指定下标的数组元素
int
numMoved = size - index -
1
;
//要移动的元素个数
if
(numMoved >
0
)
System.arraycopy(elementData, index+
1
, elementData, index, numMoved);
//移动数组元素
elementData[--size] =
null
;
// Let gc do its work
return
oldValue;
}
public
boolean
remove(Object o) {
if
(o ==
null
) {
//如果传入的参数为null
for
(
int
index =
0
; index < size; index++)
if
(elementData[index] ==
null
) {
//移除首次出现的null
fastRemove(index);
return
true
;
}
}
else
{
for
(
int
index =
0
; index < size; index++)
if
(o.equals(elementData[index])) {
fastRemove(index);
return
true
;
}
}
return
false
;
}
private
void
fastRemove(
int
index) {
//移除指定位置的元素,实现方法类似remove(int i)
modCount++;
int
numMoved = size - index -
1
;
if
(numMoved >
0
)
System.arraycopy(elementData, index+
1
, elementData, index,
numMoved);
elementData[--size] =
null
;
// Let gc do its work
}
|
5、clone方法: 1) Object clone(),返回此ArrayList实例的浅表副本(不复制这些元素本身) .
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
public
Object clone() {
try
{
ArrayList<E> v = (ArrayList<E>)
super
.clone();
//调用Object类的clone方法返回一个ArrayList对象
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();
}
}
|
以上通过对ArrayList部分关键源码的分析,知道了ArrayList底层的实现原理,关于ArrayList源码有以下几点几点总结: 1) ArrayList 底层是基于数组来实现的,可以通过下标准确的找到目标元素,因此查找的效率高;但是添加或删除元素会涉及到大量元素的位置移动,效率低。 2) ArrayList提供了三种不同的构造方法,无参数的构造方法默认在底层生成一个长度为10的Object类型的数组,当集合中添加的元素个数大于10,数组会自动进行扩容,即生成一个新的数组,并将原数组的元素放到新数组中。 3) ensureCapacity方法对数组进行扩容,它会生成一个新数组,长度是原数组的1.5倍+1,随着向ArrayList中不断添加元素,当数组长度无法满足需要时,重复该过程.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.
原文链接:http://www.cnblogs.com/fangfuhai/p/5767056.html 。
最后此篇关于Java集合框架ArrayList源码分析(一)的文章就讲到这里了,如果你想了解更多关于Java集合框架ArrayList源码分析(一)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我需要开发一个简单的网站,我通常使用 bootstrap CSS 框架,但是我想使用 Gumbyn,它允许我使用 16 列而不是 12 列。 我想知道是否: 我可以轻松地改变绿色吗? 如何使用固定布局
这个问题在这里已经有了答案: 关闭 13 年前。 与直接编写 PHP 代码相比,使用 PHP 框架有哪些优点/缺点?
我开发了一个 Spring/JPA 应用程序:服务、存储库和域层即将完成。 唯一缺少的层是网络层。我正在考虑将 Playframework 2.0 用于 Web 层,但我不确定是否可以在我的 Play
我现有的 struts Web 应用程序具有单点登录功能。然后我将使用 spring 框架创建一个不同的 Web 应用程序。然后想要使用从 struts 应用程序登录的用户来链接新的 spring 应
我首先使用Spark框架和ORMLite处理网页上表单提交的数据,在提交中文字符时看到了unicode问题。我首先想到问题可能是由于ORMLite,因为我的MySQL数据库的字符集已设置为使用utf8
我有一个使用 .Net 4.5 功能的模块,我们的应用程序也适用于 XP 用户。所以我正在考虑将这个 .net 4.5 依赖模块移动到单独的项目中。我怎样才能有一个解决方案,其中有两个项目针对不同的版
我知道这是一个非常笼统的问题,但我想我并不是真的在寻找明确的答案。作为 PHP 框架的新手,我很难理解它。 Javascript 框架,尤其是带有 UI 扩展的框架,似乎通过将 JS 代码与设计分开来
我需要收集一些关于现有 ORM 解决方案的信息。 请随意编写任何编程语言。 你能谈谈你用过的最好的 ORM 框架吗?为什么它比其他的更好? 最佳答案 我使用了 NHibernate 和 Entity
除了 Apple 的 SDK 之外,还有什么强大的 iPhone 框架可供开始开发?有没有可以加快开发时间的方法? 最佳答案 此类框架最大的是Three20 。 Facebook 和许多其他公司都使用
有人可以启发我使用 NodeJS 的 Web 框架吗?我最近开始从免费代码营学习express js,虽然一切进展顺利,但我对express到底是什么感到困惑。是全栈框架吗?纯粹是为了后端吗?我发现您
您可以推荐哪种 Ajax 框架/工具包来构建使用 struts 的 Web 应用程序的 GUI? 最佳答案 我会说你的 AJAX/javascript 库选择应该较少取决于你的后端是如何实现的,而更多
我有生成以下错误的 python 代码: objc[36554]: Class TKApplication is implemented in both /Library/Frameworks/Tk.
首先,很抱歉,如果我问的问题很明显,因为我没有编程背景,那我去吧: 我想运行一系列测试场景并在背景部分声明了几个变量(我打印它们以仔细检查它们是否已正确声明),第一个是整数,另外两个字符串为你可以看到
在我们承担的一个项目中,我们正在寻找一个视频捕获和录制库。我们的基础工作(基于 google 搜索)表明 vlc (libvlc)、ffmpeg (libavcodec) 和 gstreamer 是三
我试过没有运气的情况下寻找某种功能来杀死/中断Play中的正常工作!框架。 我想念什么吗?还是玩了!实际没有添加此功能? 最佳答案 Java stop类中没有像Thread方法那样的东西,由于种种原因
我们希望在我们的系统中保留所有重大事件的记录。例如,在数据库可能存储当前用户状态的地方,事件日志应记录对该状态的所有更改以及更改发生的时间。 事件记录工具应该尽可能接近于事件引发器的零开销,应该容纳结
那里有 ActionScript 2.0/3.0 的测试框架列表吗? 最佳答案 2010-05-18 更新 由于这篇文章有点旧,而且我刚刚收到了赞成票,因此可能值得提供一些更新的信息,这样人们就不会追
我有一个巨大的 numpy 数组列表(一维),它们是不同事件的时间序列。每个点都有一个标签,我想根据其标签对 numpy 数组进行窗口化。我的标签是 0、1 和 2。每个窗口都有一个固定的大小 M。
我是 Play 的新手!并编写了我的第一个应用程序。这个应用程序有一组它依赖的 URL,从 XML 响应中提取数据并返回有效的 URL。 此应用程序需要在不同的环境(Dev、Staging 和 Pro
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 4年前关闭。 Improve thi
我是一名优秀的程序员,十分优秀!