一、在工作中,集合对于我们来说,实在是太常用了,常见在一个查询接口中,使用起来也非常方便,当然,能了解到其工作流程,会帮助我们更好的使用它。
note : Collection接口:

一、Collection接口和常用方法
Collection集合常用遍历方式 :
1、利用父类的 Iterable 的方法 (迭代器遍历)
Iterator<T> iterator();
2、利用增强for循环 (增强for循环)note:底层仍使用迭代器
1.List 接口
note :List集合常见特性
1 . 添加顺序和取出顺序一致、且可重复
2 . 每个元素都有其对应的顺序索引、即支持索引
note :List接口三种遍历方式
1 . 利用父类的 Iterable 的方法 (迭代器遍历)
2 . 利用增强for循环 (增强for 循环)
3 . 普通for循环
a、ArrayList 实现类
note :注意事项
1 . ArrayList 可以加入多个null
2 . ArrayList 是由数组来实现数据存储的
3 . ArrayList 基本等同于Vector,除了ArrayList是线程不安全 (执行效率高) 在多线程的环境下,不建议使用ArrayList
note :扩容机制
1 . ArrayList中维护了一个Object类型的数组elementData (transient Object[] elementData)transient 表示该属性不会被序列化
2 . 当创建ArrayList对象时,如果使用的是无参构造器,则初始elementData容量为0,第一次添加,则扩容elementData为10,如需要再次扩容,则扩容elementData为1.5倍
3 . 如果使用的是指定大小的构造器,则初始elementData容量为指定大小,如果需要扩容,则直接扩容elementData为1.5倍
note :底层原理
1 . 无参构造扩容原理(不指定容量)
@SuppressWarnings({"all"})
public static void main(String[] args) {
ArrayList list = new ArrayList<>(); /1.创建集合对象
for (int i = 1; i <= 10; i++) { /2.循环向集合中添加元素
list.add(i)
}
for (int i = 11; i <= 15; i++) { /3. 循环向集合中添加元素
list.add(i);
}
list.add(119);
list.add(115);
list.add(true);
}
**note**:以下代码均为源码 按照执行顺序: a -> b -> c -> d
1.创建对象时,无参构造器中的elementData指向一个空数组
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
public ArrayList() {
this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}

2.向集合中添加元素时,扩容的过程
a: 添加过程先进入该方法
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
b: 走到该方法对集合的长度进行判断,如果为空即初始化为 DEFAULT_CAPACITY = 10,否则返回集合容纳当前元素的长度
private void ensureCapacityInternal(int minCapacity) {
ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
return Math.max(DEFAULT_CAPACITY, minCapacity);
}
return minCapacity;
}
c: 然后执行该方法,根据集合长度是否能容纳 当前元素添加完成后 的所有元素来判断是否要进行扩容
private void ensureExplicitCapacity(int minCapacity) {
modCount++;
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
d: 如果不符合扩容条件则直接向上返回,如果符合条件,则调用扩容方法 (真正的扩容方法)
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);
}
2 . 有参构造扩容原理(指定容量)
note :除了指定初始容量,其扩容机制与无参构造一致
b、Vector 实现类
note :注意事项
1 . Vector 类的定义 实现了List接口
public class Vector<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable
2 . Vector 底层也是一个对象数组
protected Object[] elementData;
3 . Vector 是线程同步的,即线程安全,Vector类的操作方法带有synchronized
public synchronized E get(int index) { if (index >= elementCount) throw new ArrayIndexOutOfBoundsException(index); return elementData(index);}
4 . 在开发中 ,需要线程同步安全时,考虑用 Vector
note : 底层原理
1 . 无参构造扩容原理
@SuppressWarnings({"all"})
public static void main(String[] args) {
Vector vector = new Vector(); /1.创建集合对象
for (int i = 0; i < 10; i++) { /2.向集合中添加元素
vector.add(i);
}
vector.add("勒布朗詹姆斯"); /3.向集合中添加元素
}
**note** : 以下代码均为源码
1.创建集合对象时,走的流程
a: 先进入无参构造器
public Vector() {
this(10);
}
b: 调用有参构造器初始化集合默认大小为10
public Vector(int initialCapacity) {
this(initialCapacity, 0);
}
c: 在调用有参构造器
public Vector(int initialCapacity, int capacityIncrement) {
super();
if (initialCapacity < 0)
throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
this.elementData = new Object[initialCapacity];
this.capacityIncrement = capacityIncrement;
}
2.向集合中添加元素时,走的流程
a: 先进入add方法
public synchronized boolean add(E e) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = e;
return true;
}
b: 然后执行ensureCapacityHelper(elementCount + 1)方法 (note : 如果当前集合大小够容纳当前元素,那么就不进行扩容操作,否则进行扩容操作,即执行grow(minCapacity)方法)
private void ensureCapacityHelper(int minCapacity) {
// overflow-conscious code
if (minCapacity - elementData.length > 0)
grow(minCapacity);
}
c: 如果符合扩容条件,则进行扩容操作
private void grow(int minCapacity) {
// overflow-conscious code
int oldCapacity = elementData.length;
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?
capacityIncrement : oldCapacity);
if (newCapacity - minCapacity < 0)
newCapacity = minCapacity;
if (newCapacity - MAX_ARRAY_SIZE > 0)
newCapacity = hugeCapacity(minCapacity);
elementData = Arrays.copyOf(elementData, newCapacity);
}
2 . 有参构造扩容原理
note :除了指定初始容量,其扩容机制与无参构造一致

note : ArrayList 与 Vector的比较

c、LinkedList 实现类
note :集合说明
1 . LinkedList底层实现了双向链表和双端队列特点
2 . 可以添加任意元素(可重复),包括null
3 . 线程不安全,没有实现同步
note :底层结构
LinkedList linkedList = new LinkedList();
for (int i = 1; i <= 10; i++) {
linkedList.add(i);
}
linkedList.add("安东尼戴维斯");
a、进入add方法
public boolean add(E e) {
linkLast(e);
return true;
}
b、进入linkLast方法,将新元素与last连接起来
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++;
}
note : ArrayList 与 LinkedList的区别

1 . 如果我们改查的操作多,选择ArrayList
2 . 如果我们增删的操作多,选择LinkedList
3 . 一般来说,在程序中,大多数都是查询,因此大部分情况下会选择ArrayList
4 . 在一个项目中,根据业务灵活选择,也可能这样,一个模块使用的是ArrayList ,另一个模块使用的LinkedList,也就是说,要根据业务来进行选择