java中集合的使用无处不在,本次对于list集合常用实现类介绍
1.List
list在java开发是的的频率非常高比如使用mybatis或者hibernate查询数据返回的实体集合常用list接收,list是一个java接口,我们常用ArrayList、linkedlist、vector等实现类来创建List对象
a)ArrayList
1.ArrayList底层数据存储基于数组
2.底层数组默认大小为10,当超过新加一个元素的数据大小超过数组大小时,创建一个新数组,新数组大小=1.5*老数组
3.多线程不安全
4.随机访问速度较快,可以直接通过数组下标返回数据
public class ArrayList<E> extends AbstractList<E>implements List<E>, RandomAccess, Cloneable, java.io.Serializable{
/*** 默认初始化大小*/
private static final int DEFAULT_CAPACITY = 10;
/*** 空数组时的数据*/
private static final Object[] EMPTY_ELEMENTDATA = {};
/**默认创建时例时空数据的值*/
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
/**集合和数据存储的元素数据,这就是ArrayList底层基于数组的原因*/
transient Object[] elementData; // non-private to simplify nested class access
/**数据的大小**/
private int size;
/**
* 无参构造方法、赋予数组默认为一个空数组
*/
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
/**
* 构造方法指定底层数组默认大小
*/
public ArrayList(int initialCapacity) {
if (initialCapacity > 0) {
this.elementData = new Object[initialCapacity];
} else if (initialCapacity == 0) {
this.elementData = EMPTY_ELEMENTDATA;
} else {
throw new IllegalArgumentException("Illegal Capacity: "+
initialCapacity);
}
}
/**
* 集合最常用方法、添加元素、
*/
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
//传入参数为当前size+1
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
//判断当时集合内数据是否为默认空数据,若为true则返回当前size+1与默认值10中大的一个数据
//这就是为什么初始化赋予的值未空数组,但是默认初始化大小为10,就是当调用add方法时赋予的size
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
//判断数据是否应该扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
//扩容至1.5倍
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);
}
b)、linkedList
1.数据插入、删除较快
2.数据遍历速度快
3.不能随机访问
4.多线程不安全
public class LinkedList<E> extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
//大小
transient int size = 0;
/**
* 标记第一个值
* 恒定不变的: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first;
/**
* 标记最后一个值
* 恒定不变: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last;
/**
* 追加元素到最后一个节点 **/
public boolean add(E e) {
linkLast(e);
return true;
}
//添加到最后一个元素
void linkLast(E e) {
final Node<E> l = last;
final Node<E> newNode = new Node<>(l, e, null);
last = newNode;
if (l == null)
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
3.Vector
1.不指定一块内存大小的数组的连续存储,即可以像数组一样操作,但可以对此数组进行动态操作。通常体现在push_back() pop_back()
2.随机访问方便,即支持[ ]操作符和vector.at()
3. 节省空间。
4. 在内部进行插入删除操作效率低。
5. 只能在vector的最后进行push和pop,不能在vector的头进行push和pop。
6. 当动态添加的数据超过vector默认分配的大小时要进行整体的重新分配、拷贝与释放
7. 多线程安全
4.CopyOnWriteArrayList
1、适合使用在读操作远远大于写操作的场景里,比如缓存。发生修改时候做copy,新老版本分离,保证读的高性能,适用于以读为主的情况。
2、多线程安全,轻量级锁实现多线程安全。
3、采用“写入时复制”策略,对容器的写操作将导致的容器中基本数组的复制,性能开销较大。所以在有写操作的情况下,CopyOnWriteArrayList性能不佳,而且如果容器容量较大的话容易造成溢出