https://blog.csdn.net/ZQ_313/article/details/84062629
List接口下常用的实现类——ArrayList
1、特点
1)底层实现是数组
2)数据可重复
3)可以有多个null
4)存储的是单个值
5)保证插入的数据有序
6)查询、修改效率高;删除、增加效率低
2、常用实现方法
int size();//获取存储数据的个数
boolean isEmpty();//判断集合是否为空
boolean contains(Object o);//判断集合当中是否存在该元素
Iterator<E> iterator();//实例化迭代器对象(遍历)
Object[] toArray();//将集合转化为数组
boolean add(E e);//往集合中添加元素
boolean remove(Object o);//从集合中删除元素(删除指定的元素)
boolean containsAll(Collection<?> c)//判断集合中是否存在传入集合的所有元素
void clear();//对集合所有元素删除
3、ArrayList源码解读
1)继承关系
public class ArrayList<E> extends AbstractList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable
继承AbstractList类,实现了List<E>接口,ArrayList是List接口的一个实现类
Cloneable 可以克隆、java.io.Serializable 可以进行序列化和反序列化操作
2)基本属性
a.数组的默认初始容量
private static final int DEFAULT_CAPACITY = 10;
因为ArrayList底层是由一个Object[]数组构成,而这个Object[]数组的默认长度是10,所以ArrayList长度默认容量是10。
b.数组的初始化使用
private static final Object[] EMPTY_ELEMENTDATA = {};
c.ArrayList的底层数据结构是数组
private transient Object[] elementData;
d.集合中存储元素的个数
private int size;
e.modCount表示的是版本控制,添加,删除,修改之类的操作都会++操作
protected transient int modCount = 0;
3)构造函数
a.//有参构造,参数表示数组初始大小
直接对elementData属性进行初始化
public ArrayList(int initialCapacity) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
this.elementData = new Object[initialCapacity];
}
b.//无参构造,elementData数组为空
public ArrayList() {
super();
this.elementData = EMPTY_ELEMENTDATA;
}
c.//构造函数,参数是集合类型的一个对象
-
public ArrayList(Collection<? extends E> c) { elementData = c.toArray();//将集合转化为数组 size = elementData.length; // c.toArray might (incorrectly) not return Object[] (see 6260652) if (elementData.getClass() != Object[].class) elementData = Arrays.copyOf(elementData, size, Object[].class); }
4)增长方式
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + (oldCapacity >> 1);//按原数组的大小进行1.5倍扩容
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);
}
5)增删改查操作
a.增加元素
public boolean add(E e) {//即相当于尾插
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
判断数组是否为空,若为空,数组大小设置为10
如果需要扩容,数组按照1.5倍大小进行扩容
将元素插入数组elementData,并且size+1
特点:存储重复数据,可以存储null
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++;
}
b.删除元素
public E remove(int index) {//按索引删除
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
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;
}
要对值进行拆包操作(list.remove(Integer.valueOf(o));)才可以调用此remove方法
特点:
数组起始元素是0
找到第一个出现的元素直接删除并返回
时间复杂度o(n)
c.获取当前元素
public E get(int index) {//通过索引位置直接查询数组elementData的元素
rangeCheck(index);
return elementData(index);
}
补充:两个集合的交集、并集、差集
并集:两集合所有元素的总和
交集:两个集合中共有元素,即你有我也有的
差集:集合a中除了和集合b共有元素之外的元素,a与b的差集;即我有你没有的
比如:集合A:1 2 3 集合B:3 4 5
则A与B的并集是1 2 3 3 4 5,交集:3,A与B的差集:1 2 ,B与A的差集:4 5
ArrayList<Integer> a=new ArrayList<>();
a.add(1);
a.add(2);
a.add(3);
ArrayList<Integer> b=new ArrayList<>();
b.add(3);
b.add(4);
b.add(5);
//两个集合的并集
a.addAll(b);
//两个集合的交集
a.retainAll(b);
//a与b的差集
b.retainAll(a);
a.removeAll(b);
ArrayList与数组的异同点?
不同点:1)ArrayList只能存储引用数据类型;而数组既可以存储基本数据类型也可以存储引用数据类型;
2)ArrayList的大小可以动态指定,它的大小可在初始化时指定也可以不指定,也就是说该对象的空间可以任意增加; 而数组在初始化时必须指定大小;
3)ArrayList不支持多维,而数组支持多维。
相同点:底层是数组,具有数组的特性,拥有索引,可以快速找到元素