Java中ArrayList类的用法与源码完全解析
system.collections.arraylist类是一个特殊的数组。通过添加和删除元素,就可以动态改变数组的长度。
一.优点
1. 支持自动改变大小的功能
2. 可以灵活的插入元素
3. 可以灵活的删除元素
二.局限性
跟一般的数组比起来,速度上差些
三.添加元素
1.publicvirtualintadd(objectvalue);
将对象添加到arraylist的结尾处
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e");
内容为
abcde
2.publicvirtualvoidinsert(intindex,objectvalue);
将元素插入arraylist的指定索引处
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.insert(0,"aa");
结果为
aaabcde
3.publicvirtualvoidinsertrange(intindex,icollectionc);
将集合中的某个元素插入arraylist的指定索引处
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); arraylist list2 = newarraylist(); list2.add("tt"); list2.add("ttt"); alist.insertrange(2,list2);
结果为
abtttttcde
四.删除
1. publicvirtualvoidremove(objectobj);
从arraylist中移除特定对象的第一个匹配项,注意是第一个
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.remove("a");
结果为
bcde
2. publicvirtualvoidremoveat(intindex);
移除arraylist的指定索引处的元素
alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.removeat(0);
结果为
bcde
3.publicvirtualvoidremoverange(intindex,intcount);
从arraylist中移除一定范围的元素。index表示索引,count表示从索引处开始的数目
alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.removerange(1,3);
结果为
4.publicvirtualvoidclear();
从arraylist中移除所有元素。
五.排序
1. publicvirtualvoidsort();
对arraylist或它的一部分中的元素进行排序。
arraylistalist=newarraylist(); alist.add("e"); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); dropdownlist1.datasource=alist;//dropdownlistdropdownlist1; dropdownlist1.databind();
结果为
eabcd
arraylistalist=newarraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.sort();//排序 dropdownlist1.datasource=alist;//dropdownlistdropdownlist1; dropdownlist1.databind();
结果为
abcde
2.publicvirtualvoidreverse();
将arraylist或它的一部分中元素的顺序反转。
arraylistalist=newarraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); alist.reverse();//反转 dropdownlist1.datasource=alist;//dropdownlistdropdownlist1; dropdownlist1.databind();
结果为
edcba
六.查找
1.publicvirtualintindexof(object);
2. publicvirtualintindexof(object,int);
3. publicvirtualintindexof(object,int,int);
返回arraylist或它的一部分中某个值的第一个匹配项的从零开始的索引。没找到返回-1。
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e"); intnindex=alist.indexof(“a”);//1 nindex=alist.indexof(“p”);//没找到,-1
4.publicvirtualintlastindexof(object);
5.publicvirtualintlastindexof(object,int);
6.publicvirtualintlastindexof(object,int,int);
返回arraylist或它的一部分中某个值的最后一个匹配项的从零开始的索引。
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("a");//同0 alist.add("d"); alist.add("e"); intnindex=alist.lastindexof("a");//值为2而不是0
7. publicvirtualboolcontains(objectitem);
确定某个元素是否在arraylist中。包含返回true,否则返回false
七.其他
1.publicvirtualintcapacity{get;set;}
获取或设置arraylist可包含的元素数。
2.publicvirtualintcount{get;}
获取arraylist中实际包含的元素数。
capacity是arraylist可以存储的元素数。count是arraylist中实际包含的元素数。capacity总是大于或等于count。如果在添加元素时,count超过capacity,则该列表的容量会通过自动重新分配内部数组加倍。
如果capacity的值显式设置,则内部数组也需要重新分配以容纳指定的容量。如果capacity被显式设置为0,则公共语言运行库将其设置为默认容量。默认容量为16。
在调用clear后,count为0,而此时capacity切是默认容量16,而不是0
3.publicvirtualvoidtrimtosize();
将容量设置为arraylist中元素的实际数量。
如果不向列表中添加新元素,则此方法可用于最小化列表的内存系统开销。
若要完全清除列表中的所有元素,请在调用trimtosize之前调用clear方法。截去空arraylist会将arraylist的容量设置为默认容量,而不是零。
arraylist alist = new arraylist(); alist.add("a"); alist.add("b"); alist.add("c"); alist.add("d"); alist.add("e");//count=5,capacity=16, alist.trimtosize();//count=capacity=5;
八.源码分析
list 接口的一个实现类,内部是用一个数组存储元素值,相当于一个可变大小的数组。
1.签名
public class arraylist<e> extends abstractlist<e> implements list<e>, randomaccess, cloneable, serializable
可以看到arraylist继承了abstractlist抽象类,它实现了list接口的大多数方法。如果要实现一个不可变的list,只要继承这个类并且实现get(int)和size方法。如果要实现可变的list,需要覆盖set(int, e)。另外,如果list的大小是可变的,还要覆盖add(int, e)和remove()方法。
2.构造器
arraylist提供了三个构造器:
arraylist() arraylist(collection<? extends e> c) arraylist(int initialcapacity)
collection接口约定,每个集合类应该提供两个”标准”构造器,一个是无参数的构造器(上面第一个),另外一个是拥有单个参数(类型为collettion)的构造器(上面第二个)。arraylist还提供了第三个构造器,其接受一个int值,用于设置arrayli的初始大小(默认大小为10)。
3.相关方法
trimtosize public void trimtosize() { modcount++; int oldcapacity = elementdata.length; if (size < oldcapacity) { elementdata = arrays.copyof(elementdata, size); } }
用于把arraylist的容量缩减到当前实际大小,减少存储容量。其中的变量modcount由abstraclist继承而来,记录list发生结构化修改(structurally modified)的次数。elementdata中实际存储了arraylist的元素,在arraylist中声明为:private transient object[] elementdata;变量size是arraylist的元素数量,当size < oldcapacity时,调用arrays.copyof方法实现缩减。
4.indexof 和 lasindexof
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; }
这两个方法返回指定元素的下标,要区分参数是否为null。lastindexof和indexof类似,只不过是从后往前搜索。
5.ensurecapacity
public void ensurecapacity(int mincapacity) { if (mincapacity > 0) ensurecapacityinternal(mincapacity); } private void ensurecapacityinternal(int mincapacity) { modcount++; // overflow-conscious code if (mincapacity - elementdata.length > 0) grow(mincapacity); } private void grow(int mincapacity) { // overflow-conscious code int oldcapacity = elementdata.length; int newcapacity = oldcapacity + (oldcapacity >> 1); if (newcapacity - mincapacity < 0) newcapacity = mincapacity; 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); }
这个方法可以确保arraylist的大小
6.add 和 addall
public void add(int index, e element) { rangecheckforadd(index); ensurecapacityinternal(size + 1); // increments modcount!! system.arraycopy(elementdata, index, elementdata, index + 1, size - index); elementdata[index] = element; size++; }
add(int index, e element)向指定位置添加元素,首先调用rangecheckforadd检查index是否有效,如果index > size || index < 0将抛出异常。然后确保容量加1,调用system.arraycopy把从index开始的元素往后移动一个位置。最后把index处的值设置为添加的元素。还有一个重载的add(e e)方法是直接把元素添加到末尾。
addall(collection<? extends e> c)和addall(int index, collection<? extends e> c)则分别是向末尾和指定位置添加collection中的所有元素。
7.remove 和 removeall
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; }
remove(object o)方法删除指定的元素。首先是查找元素位置,然后调用fastremove(index)删除,其代码如下:
private void fastremove(int index) { modcount++; int nummoved = size - index - 1; if (nummoved > 0) //把index+1往后的元素都往前移动一个位置 system.arraycopy(elementdata, index+1, elementdata, index, nummoved); elementdata[--size] = null; // let gc do its work }
重载的remove(int index)方法用于删除指定位置的元素。removerange(int fromindex, int toindex)用于删除指定位置之间的所有元素。
removeall(collection<?> c)和retainall(collection<?> c)代码如下:
public boolean removeall(collection<?> c) { objects.requirenonnull(c); return batchremove(c, false); } public boolean retainall(collection<?> c) { objects.requirenonnull(c); return batchremove(c, true); }
它们都是通过调用batchremove方法实现的,其代码如下:
private boolean batchremove(collection<?> c, boolean complement) { final object[] elementdata = this.elementdata; int r = 0, w = 0; boolean modified = false; try { for (; r < size; r++) if (c.contains(elementdata[r]) == complement) elementdata[w++] = elementdata[r]; } finally { // preserve behavioral compatibility with abstractcollection, // even if c.contains() throws. if (r != size) { system.arraycopy(elementdata, r, elementdata, w, size - r); w += size - r; } if (w != size) { // clear to let gc do its work for (int i = w; i < size; i++) elementdata[i] = null; modcount += size - w; size = w; modified = true; } } return modified; }
这个方法有两个参数,第一个是操作的collection,第二个是一个布尔值,通过设置为true或false来选择是removeall还是retainall。try里面的语句是把留下来的放在0到w之间,然后在finally中第二个if处理w之后的空间,第一个是在c.contains()抛出异常时执行。
推荐阅读
-
Java中ArrayList类的用法与源码完全解析
-
迅速掌握Java容器中常用的ArrayList类与Vector类用法
-
java arrayList遍历的四种方法及Java中ArrayList类的用法
-
迅速掌握Java容器中常用的ArrayList类与Vector类用法
-
java arrayList遍历的四种方法及Java中ArrayList类的用法
-
Java中ArrayList类的源码解析
-
Java中ArrayList类的源码解析
-
java Swing JFrame框架类中setDefaultCloseOperation的参数含义与用法示例
-
Java中的容器(集合)之ArrayList源码解析
-
Java中的容器(集合)之ArrayList源码解析