- 浏览: 37946 次
- 性别:
- 来自: 大连
最新评论
-
liwei113114:
servlet后面的BARCODE_TYPE参数传错了,参数名 ...
(转)用java生成条形码,barcode4j得应用 -
Smart_chw:
<div class="quote_title ...
(转)Struts2调用流程 -
lishijia:
看起来确实费劲。。。
(转)Struts2调用流程 -
JArcher:
建议图文结合。。。
(转)Struts2调用流程 -
free_zk:
实在是没有办法看了
(转)Struts2调用流程
ArrayList是List接口的一个可变长数组实现。实现了所有List接口的操作,并允许存储null值。除了没有进行同步,ArrayList基本等同于Vector。在Vector中几乎对所有的方法都进行了同步,但ArrayList仅对writeObject和 readObject进行了同步,其它比如add(Object)、remove(int)等都没有同步。
1.存储
ArrayList使用一个Object的数组存储元素。
private transient Object elementData[];
ArrayList实现了java.io.Serializable接口,这儿的transient标示这个属性不需要自动序列化。下面会在writeObject()方法中详细讲解为什么要这样作。
2.add和remove
- public boolean add(Object o) {
- ensureCapacity(size + 1); // Increments modCount!!
- elementData[size++] = o;
- return true;
- }
public boolean add(Object o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; }
注意这儿的ensureCapacity()方法,它的作用是保证elementData数组的长度可以容纳一个新元素。在“自动变长机制”中将详细讲解。
- public Object remove(int index) {
- RangeCheck(index);
- modCount++;
- Object oldValue = 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 Object remove(int index) { RangeCheck(index); modCount++; Object oldValue = 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; }
RangeCheck()的作用是进行边界检查。由于ArrayList采用一个对象数组存储元素,所以在删除一个元素时需要把后面的元素前移。删除一个元素时只是把该元素在elementData数组中的引用置为null,具体的对象的销毁由垃圾收集器负责。
modCount的作用将在下面的“iterator()中的同步”中说明。
注:在前移时使用了System提供的一个实用方法:arraycopy(),在本例中可以看出System.arraycopy()方法可以对同一个数组进行操作,这个方法是一个native方法,如果对同一个数组进行操作时,会首先把从源部分拷贝到一个临时数组,在把临时数组的元素拷贝到目标位置。
3.自动变长机制
在实例化一个ArrayList时,你可以指定一个初始容量。这个容量就是elementData数组的初始长度。如果你使用:
ArrayList list = new ArrayList();
则使用缺省的容量:10。
public ArrayList() {
this(10);
}
ArrayList提供了四种add()方法,
- public boolean add(Object o)
- public void add(int index, Object element)
- public boolean addAll(Collection c)
- public boolean addAll(int index, Collection c)
public boolean add(Object o) public void add(int index, Object element) public boolean addAll(Collection c) public boolean addAll(int index, Collection c)
在每一种add()方法中,都首先调用了一个ensureCapacity(int miniCapacity)方法,这个方法保证elementData数组的长度不小于miniCapacity。ArrayList的自动变长机制就是在这个方法中实现的。
- public void ensureCapacity(int minCapacity) {
- modCount++;
- int oldCapacity = elementData.length;
- if (minCapacity > oldCapacity) {
- Object oldData[] = elementData;
- int newCapacity = (oldCapacity * 3)/2 + 1;
- if (newCapacity < minCapacity)
- newCapacity = minCapacity;
- elementData = new Object[newCapacity];
- System.arraycopy(oldData, 0, elementData, 0, size);
- }
- }
public void ensureCapacity(int minCapacity) { modCount++; int oldCapacity = elementData.length; if (minCapacity > oldCapacity) { Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; elementData = new Object[newCapacity]; System.arraycopy(oldData, 0, elementData, 0, size); } }
从这个方法实现中可以看出ArrayList每次扩容,都扩大到原来大小的1.5倍。
每种add()方法的实现都大同小异,下面给出add(Object)方法的实现:
- public boolean add(Object o) {
- ensureCapacity(size + 1); // Increments modCount!!
- elementData[size++] = o;
- return true;
- }
public boolean add(Object o) { ensureCapacity(size + 1); // Increments modCount!! elementData[size++] = o; return true; }
4.iterator()中的同步
在父类AbstractList中定义了一个int型的属性:modCount,记录了ArrayList结构性变化的次数。
protected transient int modCount = 0;
在ArrayList的所有涉及结构变化的方法中都增加modCount的值,包括:add()、remove()、addAll()、removeRange()及clear()方法。这些方法每调用一次,modCount的值就加1。
注:add()及addAll()方法的modCount的值是在其中调用的ensureCapacity()方法中增加的。
AbstractList中的iterator()方法(ArrayList直接继承了这个方法)使用了一个私有内部成员类Itr,生成一个Itr对象(Iterator接口)返回:
public Iterator iterator() {
return new Itr();
}
Itr实现了Iterator()接口,其中也定义了一个int型的属性:expectedModCount,这个属性在Itr类初始化时被赋予ArrayList对象的modCount属性的值。
int expectedModCount = modCount;
注:内部成员类Itr也是ArrayList类的一个成员,它可以访问所有的AbstractList的属性和方法。理解了这一点,Itr类的实现就容易理解了。
在Itr.hasNext()方法中:
public boolean hasNext() {
return cursor != size();
}
调用了AbstractList的size()方法,比较当前光标位置是否越界。
在Itr.next()方法中,Itr也调用了定义在AbstractList中的get(int)方法,返回当前光标处的元素:
- public Object next() {
- try {
- Object next = get(cursor);
- checkForComodification();
- lastRet = cursor++;
- return next;
- } catch(IndexOutOfBoundsException e) {
- checkForComodification();
- throw new NoSuchElementException();
- }
- }
public Object next() { try { Object next = get(cursor); checkForComodification(); lastRet = cursor++; return next; } catch(IndexOutOfBoundsException e) { checkForComodification(); throw new NoSuchElementException(); } }
注意,在next()方法中调用了checkForComodification()方法,进行对修改的同步检查:
- final void checkForComodification() {
- if (modCount != expectedModCount)
- throw new ConcurrentModificationException();
- }
final void checkForComodification() { if (modCount != expectedModCount) throw new ConcurrentModificationException(); }
现在对modCount和expectedModCount的作用应该非常清楚了。在对一个集合对象进行跌代操作的同时,并不限制对集合对象的元素进行操作,这些操作包括一些可能引起跌代错误的add()或remove()等危险操作。在AbstractList中,使用了一个简单的机制来规避这些风险。这就是modCount和expectedModCount的作用所在。
5.序列化支持
ArrayList实现了java.io.Serializable接口,所以ArrayList对象可以序列化到持久存储介质中。ArrayList的主要属性定义如下:
private static final long serialVersionUID = 8683452581122892189L;
private transient Object elementData[];
private int size;
可以看出serialVersionUID和size都将自动序列化到介质中,但elementData数组对象却定义为transient了。也就是说 ArrayList中的所有这些元素都不会自动系列化到介质中。为什么要这样实现?因为elementData数组中存储的“元素”其实仅是对这些元素的一个引用,并不是真正的对象,序列化一个对象的引用是毫无意义的,因为序列化是为了反序列化,当你反序列化时,这些对象的引用已经不可能指向原来的对象了。所以在这儿需要手工的对ArrayList的元素进行序列化操作。这就是writeObject()的作用。
- private synchronized void writeObject(java.io.ObjectOutputStream s)
- throws java.io.IOException{
- // Write out element count, and any hidden stuff
- s.defaultWriteObject();
- // Write out array length
- s.writeInt(elementData.length);
- // Write out all elements in the proper order.
- for (int i=0; i<size; i++)
- s.writeObject(elementData[i]);
- }
private synchronized void writeObject(java.io.ObjectOutputStream s) throws java.io.IOException{ // Write out element count, and any hidden stuff s.defaultWriteObject(); // Write out array length s.writeInt(elementData.length); // Write out all elements in the proper order. for (int i=0; i<size; i++) s.writeObject(elementData[i]); }
这样元素数组elementData中的所以元素对象就可以正确地序列化到存储介质了。
对应的readObject()也按照writeObject()方法的顺序从输入流中读取:
- private synchronized void readObject(java.io.ObjectInputStream s)
- throws java.io.IOException, ClassNotFoundException {
- // Read in size, and any hidden stuff
- s.defaultReadObject();
- // Read in array length and allocate array
- int arrayLength = s.readInt();
- elementData = new Object[arrayLength];
- // Read in all elements in the proper order.
- for (int i=0; i<size; i++)
- elementData[i] = s.readObject();
- }
private synchronized void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { // Read in size, and any hidden stuff s.defaultReadObject(); // Read in array length and allocate array int arrayLength = s.readInt(); elementData = new Object[arrayLength]; // Read in all elements in the proper order. for (int i=0; i<size; i++) elementData[i] = s.readObject(); }
发表评论
-
POI读取EXCEL进行sheet复制
2011-08-10 12:10 2741/****************************** ... -
(转)一个简单的Spring的AOP例子
2011-05-04 10:31 757经过这段日子的学习和使用Spring,慢慢地体会到Spring ... -
POI设置EXCEL单元格格式为文本、小数、百分比、货币、日期、科学计数法和中文大写
2011-04-28 15:55 1306再读本篇文章之前,请先看我的前一篇文章,前一篇文章中有重点 ... -
(转)iReport与JasperReport简介
2011-01-31 08:45 1321一、iReport与JasperReport简介 ... -
(转)用java生成条形码,barcode4j得应用
2011-01-26 09:54 2784最近一个oa系统用到了 ... -
(转)条形码barcode4j的使用
2011-01-26 09:51 929 -
如何成功制作可执行的Jar包
2010-12-19 12:23 783今天试了一下制作可执行的Jar文件的方法。 具体如下: 首 ... -
bat运行jar文件
2010-12-19 09:07 1597set JAVA_HOME=D:\Users\Java\jdk ... -
(转)JAR文件包及jar命令详解
2010-12-19 07:39 826常常在网上看到 ... -
(转)在java程序中如何知道数据库表的主键
2010-12-11 07:59 1431有同事问到在程序中怎样知道数据库表中那 ... -
(转)浅谈JDBC事务和JTA (XA)事务
2010-11-10 09:46 1124事务简介 一般情 ... -
Java, 面试题, Spring
2010-11-05 14:36 1312Java, 面试题, Spring 113. 什么是aop,a ... -
JSP 抛出一些URI异常的解决方法
2010-05-31 10:24 1299本文来自CSDN博客:http://blog.csdn.net ... -
(转)ECSide入门(资料整理)
2010-03-24 14:14 831ECSide是有一个基于jsp tag的开源列表组件.简 ... -
(转)Struts2调用流程
2010-01-07 14:11 15041. 当Servlet容器接收到一个请求后,将请求交给你在we ... -
Struts1和Struts2的区别和对比
2009-08-07 20:46 6961.Action 类: • Struts1要求Action类 ...
相关推荐
在这个ArrayList实现中,第一层散列可能是用来快速定位元素的位置,而第二层散列可能是为了处理散列冲突,确保每个元素都有一个唯一的索引。这种双层散列结构可以显著减少查找和插入的时间复杂度,使其接近O(1)。 ...
《深入Java集合学习系列:ArrayList的实现原理》 在Java编程中,ArrayList是集合框架中一个重要的类,属于List接口的实现,它提供了动态数组的功能,允许我们在集合中存储、添加、删除元素,并且可以按索引访问。这...
ArrayList是Java集合框架中的一个重要类,它实现了List接口,用于存储可变大小的有序对象列表。ArrayList通过数组来存储元素,因此可以快速访问任意位置的元素,但插入和删除元素时可能需要移动其他元素,这可能导致...
在.NET Framework中,`ArrayList`实现了`ICollection`和`IList`接口,这意味着它支持列表的基本功能,如添加、删除元素等。 #### 二、如何使用ArrayList? 创建一个`ArrayList`实例非常简单: ```csharp ...
在本项目中,我们将深入探讨ArrayList的基本实现和在Visual Studio环境下的使用方法。 ArrayList的基础概念: 1. 动态数组:ArrayList实际上是一个可以自动调整大小的动态数组,可以根据需要自动扩展或收缩容量。 2...
ArrayList是一个基于数组实现的动态列表,可以存储任何类型的数据,并且支持动态扩容。在本实例中,我们将深入探讨ArrayList的常用操作、特性和注意事项。 一、ArrayList的构造方法 ArrayList提供了几种构造方法,...
- ArrayList是一个基于数组实现的动态列表,它允许存储任意类型的对象,这得益于C#的类型擦除特性。 - ArrayList内部维护了一个Object类型的数组,当添加或删除元素时,它会自动调整数组大小以适应变化。 2. **...
- **实现接口**:ArrayList 实现了 `java.util.List`、`java.util.RandomAccess` 和 `java.util.Iterator` 等接口,提供了丰富的操作方法。 - **性能考虑**:ArrayList 的操作速度通常比 LinkedList 快,因为它是...
ArrayList是Java集合框架中的一员,它是一个基于数组实现的动态列表。ArrayList的主要特点是其容量能够自动增长,以适应添加更多的元素。在Java中,ArrayList类位于`java.util`包下,它实现了`List`接口,同时也实现...
ArrayList是Java中一种常见的动态数组实现,它是List接口的一个实现类,主要特点是可以在运行时自动调整其容量以适应元素数量的变化。ArrayList的核心概念基于数组,但比数组更加灵活,因为它支持动态增长和缩小,...
- 如果ArrayList包含复杂对象,考虑使用ObjectDataSource和DataBinding,这有助于实现数据层和UI层的解耦。 6. 事件处理: - 可以监听ListBox的SelectedIndexChanged事件,以便在用户选择新项时执行相应操作。 -...
在了解ArrayList的源码分析时,我们主要探讨其在Java Development Kit (JDK) 1.8中的实现。ArrayList是一个非常重要的集合框架,用于动态数组的实现,其功能类似于数组,但可以在运行时动态调整大小。它是一个非线程...
在IT领域,特别是Java编程中,ArrayList和LinkedList是两种非常重要的数据结构,它们都是List接口的实现类。理解这两者的区别对于优化程序性能至关重要。面试官询问这些知识点,旨在评估应聘者的理论基础和实践能力...
ArrayList类实现了List接口,提供了可变大小的数组,允许我们在列表的任何位置进行添加、删除和修改元素的操作。这篇ArrayList演示将通过一系列实例帮助我们深入理解ArrayList的用法。 首先,ArrayList的基本操作...
ArrayList属于List接口的实现,而HashMap则实现了Map接口。两者在用途、性能和特性上都有所不同。 ArrayList是一个动态数组,它允许我们在集合中按索引顺序访问元素。它通过内部维护一个数组来存储元素,当添加...
ArrayList的removeAll方法的实现机制是通过循环遍历ArrayList中的每个元素,然后使用contains方法判断该元素是否在另外一个集合中,如果在,则删除该元素。这种实现机制的问题是,它需要两层循环,时间复杂度为O(m*n...
相比于普通的数组,`ArrayList`提供了更加灵活的功能,比如动态地增加和减少元素,以及实现`ICollection`和`IList`接口的能力。这使得`ArrayList`成为一种在不知道数组大小的情况下处理数据的有效方式。 #### 二、...
在提供的资源中,"ClassLibrary1"可能是一个包含ArrayList实现的类库项目,"list01.sln"是解决方案文件,用于打开和管理项目,"list01"可能是项目的源代码文件夹,而"list01.suo"是Visual Studio的用户选项文件,...
ArrayList是.NET框架中System.Collections命名空间下的一个类,它是基于数组实现的动态列表。ArrayList提供了在集合中添加、删除、查找和访问元素的功能,适用于存储各种类型的数据。在这个ArrayList测试中,我们将...