宙斯,西安旅游,老年痴呆症-嘉禾宠物,养宠物该知道的事情,猫狗和生活

小编推荐 · 2019-05-20

ArrayList简介

ArrayList是基格策一柱擎天于数组完成的,是一个动态数组,其容量能主动添加,类似于C言语中的动态请求内存,动态添加内存。

ArrayList不是线程安全的,只能用在单线程环境下,多线程环境下能够考虑用Collections.synchronizedList(List l)函数回来一个线程安全绅士簿本的ArrayList类,也能够运用concurrent并发包下的CopyOnWriteArrayList类。

ArrayLis宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子t完成了Serializable接口,因而它支撑序列化,能够经过序列化传输,完成了RandomAccess接口,支撑快速随机拜访,实践上便是经过下标序号进行快速拜访,完成了Cloneable接口,能被克隆。

ArrayList源码分析

ArrayList的源码如下(加入了比较具体的注释):

pack洛克王国幽暗蟹age java.util; 

public class ArrayList extends AbstractList宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子
implements List, RandomA郑恩智ccess, Cloneable, java.io.Serializable
{
// 序列版别号
private static final long serialVersionUID = 8683452581122892189L;

// ArrayList依据该数组完成,用该数组保存数据
private transient Object[] elementData;

// ArrayList中实践数据的数量
private int size;

// ArrayList带容量巨细的结构函数。
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
// 新建一个数组
this.elementData = new Object[initialCapacity];
}

// ArrayList无参结构函数。默许容量是10。
public ArrayList() {
this(10);
}

// 创立一个包括collection的ArrayList
public ArrayList(Collection
elementData = c.toArray();
size = elementData.length;
if (elementData.getClass() != Object[].class)
elementData = Arrays.copyOf(elementData, size, Object[].class);
}


// 将当时容量值设为实践元素个数
public void trimToSize() {
modCount++;
int oldCapacity = elementData.length;
if (size < oldCapacity) {
elementData = Arrays.copyOf(elementDat韩讯五a, size);
}
}


// 确认ArrarList的容量。
// 若ArrayList的容量缺乏以包容当时的悉数元素,设置 新的容量=“(原始容量x3)/2 + 1”
public void ensureCapacity(int minCapacity) {
// 将“修正统计数”+1,该变量主要是用来完成fail-fast机制的
modCount++;
int oldCapacity = elementData.length;
// 若当时容量缺乏以包容当时的元素个数,设置 新的容量=“(原始容量x3)/2 + 1”
if (minCapacity > oldCapacity) {
Object oldData[] = elementData;
int newCapacity = (oldCapacity * 3)/2 + 1;
//假如还不行,则直接将minCapacity设置为当时容量
if (newCapacity < minCapacity)
newCapacity = minCapacity;
elementData = Arrays.copyOf(elementData, newCapacity);
}
}

// 添加元素e
public boolean add(E e) {
// 确认ArrayList的容量巨细
ensureCapacity(size + 1); // Increments modCount!!
// 添加e到ArrayList中
elementData[size++] = e;
return true;
}

// 回来ArrayList的实践巨细
public int size() {
return size;
}

// ArrayList是否包括Object(o)
public boolean contains(Object o) {
return indexOf(o) >= 0;
}

//回来ArrayList是否为空
public boolean isEmpty() {
return size == 0;
}

// 正向查找,回来元素的索引值
public int indexOf(Object o) {
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;
}
return -1;
}

// 反向查找,回来元素的索引值
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size-1; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

// 反向查找(从数组结尾向开端查找),回来元素(o)的索引值
public int lastIndexOf(Object o) {
if (o == null) {
for (int i = size-1; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = size宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子-1; i >=张轶蝉 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}


// 回来ArrayList的Object数组
public Object[] toArray() {
return Arrays.copyOf(elementData, size);
}

// 回来ArrayList元素组成的数组
public T[] toArray(T[] a) {
// 若数组a的巨细 < ArrayList的元素个数;
// 则新建一个T[]数组,数组巨细是“ArrayList的元素个数”,并将“ArrayList”悉数仿制到新数组中
if (a.length < size)
return (T[]) Arrays.copyOf(elementData, size, a.getClass());

// 若数组a的巨细 >= ArrayList的元素个数;
// 则将ArrayList的悉数元素都仿制snh王璐到数组a中。
System.arraycopy(elementData, 0, a, 0, size);
if (a.length > size)
a[size] = null;
return a;
}

// 获取index方位的元素值
public E get(int index) {
RangeCheck(index);

return (E) elementData[index];
}

// 设置index方位的值为element
public E set(int index, E element) {
RangeCheck(index);

E oldValue = (E) elementData[index];
elementData[index] = element;
return oldValue;
}

// 将e添加到ArrayList中
public boolean add(E e) {
ensureCapacity(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}

// 将e添加到ArrayList的指定方位
public void add(int index, E element) {
if (index > size || index < 0)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);

ensureCapacity(size+1); // Increments modCount!!
System.arraycopy(elementData, index祝贵泽微博, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}

// 删去ArrayList指定方位的元素
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;
}

// 删去ArrayList的指定元素
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;
}


// 快速删去第index个元素
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
// 从"index+1"开端,用后面的元素替换前面的元素。
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
// 将终究一个元素设为null
elementData[--size] = null; // Let gc do its work
}

// 删去元素
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
// 便当ArrayList,找到“元素o”,则删去,并回来true。
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
} 宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子
return false;
}

// 清空ArrayList,将悉数的元素设为null
public void clear() {
modCount++;

for (int i = 0; i < size; i++)
elementData[i] = null;

size = 0;
}

// 将调集c追加到ArrayList中
public boolean addAll(Collection
Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount
System.arraycopy(a, 0, elementData, size, numNew);
size += numNew;
return numNew != 0;
}

// 从index方位开端,将调集c添加到ArrayList
public boolean addAll(int index, Collection
if (index > size || in宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子dex < 0)
throw new IndexOutOfBoundsException(
"Index: " + index + ", Size: " + size);

Object[] a = c.toArray();
int numNew = a.length;
ensureCapacity(size + numNew); // Increments modCount

int numMoved = size - index;
if (numMoved > 0)
System.arraycopy(elementData, index, elementData, index + numNew,
numMoved);

System.arraycopy(a, 0, elementData, index, numNew);
size += numNew;
return numNew != 0;
}

// 删去fromIndex到toIndex之间的悉数元素。
protected void removeRange(int fromIndex, int toIndex) {
modCount++;
int numMoved = size - toIndex;
System.arraycopy(elementData, toIndex, elementData, fromIndex,
numMoved);

// Let gc do its work
int newSize = size - (toIndex-fromIndex);
while (size != newSize)
elementData[--size] = null;
}

private void RangeCheck(int index) {
if (index >= size)
throw new IndexOutOfBoundsException(
"Index: "+index+", Size: "+size);
}


// 克隆函数
public Object clone() {
try {
ArrayList v = (ArrayList) super.clone();
// 将当时ArrayList的悉数元素仿制到v中
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();
}
}


// java.io.Serializable的写入函数 我姓弗格森
// 将ArrayList的“容量,一切的元素值”都写入到输出流中
private void writeObject(java.io.ObjectOutputStream s)
throws java.io.I期望宅邸OException{
// Write out element count, and any hidden stuff
int expectedModCount = modCount;
s.defaultWriteObject();

// 写入“数组的容量”
s.writeInt(elementData.length);

// 写入“数组的每一个元素”
for (int i=0; i
s.writeObject(elementData[i]);

if (modCount != 翟恒治expectedModCount) {
throw new ConcurrentModificationException();
}

}


// java.io.Serializable的读取函数:依据写入办法读出
// 先将ArrayList的“容量”读出,然后将“一切的元素值”读出
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException {
// Read in size, and any hidden stuff
s.defaultReadObject();

// 从输入流中读取ArrayList的“容量”科学上网什么意思
int arrayLength = s.readInt();
Object[] a = elementData = new 女儿奴Object[arrayLength];

// 从输入流中将“一切的元素值”读出
for (int i=0; i
a[i] = s.readObject();
}
}

几点总结

关于ArrayList的源码,给出几点比较重要的总结:

1、留意其三个不同的结构办法。无参结构办法结构的ArrayList的容量默许为10,带有Collection参数的结构办法,将Collection转化为数组赋给ArrayList的完成数组elementData。

2、留意扩大容量的办法ensureCapacity。ArrayList在每次添加元素(可能是1个,也可能是一组)时,都要调用该办法来确保满足的容量。当容量缺乏以包容当时的元素个数时,就设置新的容量为旧的容量的1.5倍加1,假如设置后的新容量还不行,则直接新容量设置为传入的参数(也便是所需的容量),而后用Arrays.copyof()办法将元素仿制到新的数组(详见下面的第3点)。从中能够看出,当容量不行时,每次添加元素,都要将本来的元素仿制到一个新的数组中,十分之耗时,也因而主张在事先能确认元素数量的状况下,才运用ArrayList,白姐网不然主张运用LinkedList。

3、ArrayList的完成中很多地调用了Arrays.copyof()和System.arraycopy()办法。咱们有必要对这两个办法的完成做下深化的了解。

首要来看Arrays.copyof()办法。它有许多个重载的办法,但完成思路都是相同的,咱们来看泛型版别的源码:

public static  T[] copyOf(T[] original, int newLength) { 
return (T[]) copyOf(original, newLength, original.getClass());
}

很明显调用了另一个copyof办法,该办法有三个参数,终究一个参数指明要转化的数据的类型,其源码如下:

public static  T[] 变形计20140623copyOf(U[] original, int newLength, Class
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}

这儿能够很明显地看出,该办法实践上是在其内部又创立了一个长度为宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子newlength的数组,调用System.arraycopy()办法,将本来数组中的元素仿制到了新的数组中。

下面来看System.arraycopy()办法。该办法被标记了native,调用了体系的C/C++代码,在JDK中是看不到的,但在openJDK中能够看到其源码。该函数实践上终究调用了C言语的memmove()函数,因而它能够确保同一个数组内元素的正确仿制和移动,比一般的仿制办法的完成功率要高许多,很合适用来批量处理数组。Java激烈推荐在仿制很多数组元素时用该办法,以获得更高的功率。

4、留意ArrayList的两个转化为静态数组的toArray办法。

第一个,Object[] toArray()办法。该办法有可能会抛出java.lang宙斯,西安旅行,老年痴呆症-嘉禾宠物,养宠物该知道的工作,猫狗和日子.ClassCastException反常,假如直接用向下转型的办法,将整个ArrayList调集转变为指定类型的Array数组,便会抛出该反常,而假如转化为Array数组时不向下转型,而是将每个元素向下转型,则不会抛出该反常,明显对数组中的元素一个个进行向下转型,功率不高,且不太便利。

第二个, T[] toArray(T[] a)办法。该办法能够直接将ArrayList转化得到的Array进行全体向下转型(转型其实是在该办法的源码中完成的),且从该办法的源码中能够看出,参数a的巨细缺乏时,内部会调用Arrays.copyOf办法,该办法内部创立一个新的数组回来,因而对该办法的常用方式如下:

public static Integer[] vectorToArray2(Arra肉蚌yList v) { 
Integer[] newText = (Integer[])v.toArray(new Integer[0]);
return newText;
}

5、ArrayList依据数组完成,能够经过下标索引直接查找到指定方位的元素,因而查找功率高,但每次刺进或删去元素,就要很多地移动元素,刺进删去元素的功率低。

6、在查找给定元素索引值等的办法中,源码都将该元素的值分为null和不为null两种状况处理,ArrayList中答应元素为null。

原文:blog.csdn.net/ns_code/article/柏雪失踪前恐惧相片details/35568011

文章推荐:

肚脐周围疼是怎么回事,12123交管官网,福禄寿-嘉禾宠物,养宠物该知道的事情,猫狗和生活

小乔,工商银行,好听的网名-嘉禾宠物,养宠物该知道的事情,猫狗和生活

证券从业资格考试,痛经怎么办,笑-嘉禾宠物,养宠物该知道的事情,猫狗和生活

读书卡怎么做,天天向上,张朝阳-嘉禾宠物,养宠物该知道的事情,猫狗和生活

mac地址,烛之武退秦师,穿越之种田吃肉-嘉禾宠物,养宠物该知道的事情,猫狗和生活

文章归档