ArrayList是List接口的一个子类,它在底层通过一个数组实现了数据的存储,相比于普通的数组而言,ArrayList的长度可变,这是它的一大优点。ArrayList中的数据是有序可重复的,下面来看看ArrayList的一些基本属性和方法以及简单Integer型ArrayList的自己实现。
1.基本属性与特点
·通过查询源码可以看出其底层数组的默认初始化大小为10:
·其数组的扩容方式是扩大为当前数组长度的1.5倍
·ArrayList 实现java.io.Serializable接口,这意味着ArrayList支持序列化,能通过序列化去传输。
·ArrayList中的操作不是线程安全的,所以,建议在单线程中才使用ArrayList。
·ArrayList包含了两个重要的对象:elementData 和 size,elementData 是”Object[]类型的数组”,它保存了添加到ArrayList中的元素,size 则是动态数组的实际大小。
2.基本常用方法
·add()添加元素,当参数为元素时返回值是boolean型,当参数是下标和元素时无返回值,其时间复杂度是O(1)
ArrayList<Integer> array = new ArrayList<>();
// 插入到数据的最后
array.add(1);
// 插入到指定的1号位置,原1号及其以后位置元素一次后迁一位
array.add(1, 2);
注:在ecalipse中要求右边也要写上数据类型,即ArrayList<Integer> array = new ArrayList<Integer>();
但是在IDEA中不需要,我用的是IDEA,所以都不再写。
·addAll()将一个集合添加到指定集合,返回值是boolean型
ArrayList<Integer> array1 = new ArrayList<>();
ArrayList<Integer> array2 = new ArrayList<>();
// 将集合2中的元素依次尾插到集合1中
array1.addAll(array2);
// 将集合2中的元素从集合1的2号位置开始依次插入。集合1的元素对应后移
array1.addAll(2, array2);
·remove()删除元素,当参数是索引时,返回值是想要删除的元素,当参数是元素时,返回值是boolean型,其时间复杂度是O(1)
// 当参数为int型时,哪怕你的初衷是想删除数据2,但是系统会将2当做索引处理,
// 所以当集合中存储的是int型的数据的时候,只能通过索引的方式来删除数据
array.remove(2);
·removeAll(C c)从array中删除其包含集合array1的所有元素,返回值是boolean
array.removeAll(array1);
·clear()清空集合,无返回值
arra.clear();
·retainAll(C c)保留集合array与array1共有的元素,返回值是boolean型
array.retainAll(array1);
·contains(O o)是否包含指定元素,返回值是boolean型
array.contains(2);
·get(int index)获取指定元素,其时间复杂度是O(1)
array.get(2);
·set()用指定元素替换指定位置的元素,并返回旧值,其时间复杂度是O(1)
// 用5替换2号位置的元素,返回旧值
array.set(2, 5);
3.ArrayList的迭代器
迭代器是一种提供对容器进行访问的方法,而不暴露容器内部细节的工具,它的内部有hasNext()、next()和remove()方法,一般的使用格式为:
Iterator<Integer> integer = array.iterator();
while (integer.hasNext()){
System.out.print(integer.next() + " ");
}
注意在迭代的时候不能对数据进行任何修改,即
Iterator<Integer> integer = array.iterator();
while (integer.hasNext()){
array.add(1);
array.remove(2);
System.out.print(integer.next() + " ");
}
以上操作会抛出异常,源码中有如下代码:
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
public boolean hasNext() {
return cursor != size;
}
其中expectedModCount记录的是当前的迭代器号,每当对数据进行一次操作,expectedModCount都会加1,所以在迭代器中对数据进行操作,expectedModCount就会改变,由于前后expectedModCount不一致,就会导致出错。
总结:
·ArrayList集合适用于对大型数据的查询操作,因为其底层是一个数组,由于索引的存在而查询便捷
·removeAll(C c)方法可以用于求两个集合的差集
·retainAll(C c)方法可以求两个集合的交集
·addAll(C c)方法可以求两个集合的并集
·使用迭代器遍历集合时严禁修改数据,此条适用于所有Collection集合。
4.ArrayList的简单实现
import java.util.Arrays;
/**
* description:实现ArrayList
*
* @author ajie
*/
class MyArrayList<T> {
/**
* 默认初始容量
*/
private static final int MENDACITY = 10;
/**
* 底层数组
*/
private int[] array;
/**
* 容量
*/
private int size;
/**
* 无参构造函数
*/
public MyArrayList() throws Exception {
this(MENDACITY);
}
/**
* 指定容量构造函数
*
* @param capacity
* @throws Exception 非法容量
*/
public MyArrayList(int capacity)throws Exception {
if (capacity < 0) {
throw new Exception("error capacity!");
}
this.size = -1;
this.array = new int[capacity];
}
/**
* 添加元素
*
* @param value
*/
public void add(Integer value) {
if (size < array.length - 1) {
array[++size] = value;
} else {
array = Arrays.copyOfRange(array, 0, (3 * array.length) >> 1);
array[++size] = value;
}
}
/**
* 添加数组
*
* @param arr
*/
public void addAll(int[] arr) {
if (array.length - 1 > size + arr.length) {
System.arraycopy(arr, 0, array, size + 1, arr.length);
} else {
array = Arrays.copyOfRange(array, 0, size + 1 + arr.length);
System.arraycopy(arr, 0, array, size + 1, arr.length);
}
size = size + arr.length;
}
/**
* 默认删除
*
* @return
*/
public int remove() {
if (array.length == 0) {
return -1;
}
int val = array[size];
array[size--] = -1;
return val;
}
/**
* 指定下标删除
*
* @param index
* @throws Exception 非法下标
*/
public boolean remove(int index) throws Exception {
if (array.length == 0 || index < 0 || index > size) {
throw new Exception("error index!");
} else {
for (int i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
array[size--] = -1;
return true;
}
}
/**
* 修改
*
* @param index
* @param val
* @return
* @throws Exception 角标越界
*/
public int set(int index, Integer val) throws Exception {
if (index < 0 || index > size) {
throw new Exception("out of array boundary!");
}
int oldValue = array[index];
array[index] = val;
return oldValue;
}
/**
* 获取
*
* @param index
* @return
*/
public int get(int index) {
return (index < 0 || index > size) ? -1 : array[index];
}
public void print() {
for (int i = 0; i <= size; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
}
注:以上使用的API版本为JDK1.7.0_81