
我们学习List下面ArrayList,LinkedList,Vector类即可!
学习的重点就是了解他们的底层结构,扩容原理,通过源码进行学习!
List接口下的一些常用方法

@SuppressWarnings("all")
public class ArrayList_ {
public static void main(String[] args) {
List list = new ArrayList();
//添加单个元素
for (int i = 0; i <10; i++) {
list.add(i);
}
//将list集合转换成数组进行打印!
System.out.println(Arrays.toString(list.toArray()));
//添加list集合
List list1 = new ArrayList();
list1.add(666);
list1.add(888);
//在1索引位置插入list1集合
list.addAll(1,list1);
//迭代器打印!
Iterator iterator = list.iterator();
while(iterator.hasNext()){
System.out.print(iterator.next()+" ");
}
//删除元素
list.remove(new Integer(666));
//判断是否包含元素!
list.contains(666);
//删除整个list
list.removeAll(list1);
//返回最后一个9的下标位置!
System.out.println("\n"+Arrays.toString(list.toArray()));
System.out.println("从后往前找9的下标:"+list.lastIndexOf(9));
System.out.println("6的下标:"+list.indexOf(6));
System.out.println("拆分list集合");
List tmp = list.subList(5,10);
System.out.println("tmp:"+Arrays.toString(tmp.toArray()));
//更改元素!
System.out.println("更改前:"+list.get(0)+list.set(0,9)+"更改后:"+list.get(0));
//排序:传入排序接口!
System.out.println("排序前:"+Arrays.toString(list.toArray())+"\n排序后:");
list.sort(new Comparator() {
@Override
public int compare(Object o1, Object o2) {
return (Integer) o1 - (Integer)o2;//升序
}
});
//增强for遍历!
for (Object object : list) {
System.out.print(object+" ");
}
}
}

ArrayList底层是由数组实现的!
ArrayList维护了一个elementData数组,由transient修饰不可序列化!
我们通过IDEA调试从而分析ArrayList底层结构和扩容机制
我们通过下面的代码进行ArrayList无参扩容机制的分析
public class ArrayList_ {
public static void main(String[] args) {
//无参扩容机制!
ArrayList list = new ArrayList();
//默认为 0 第一次添加扩容为 10
for (int i = 0; i <10; i++) {
list.add(i);
}
//后续扩容1.5!
list.add(11);
}
}
elementData数组长度为0

第一次扩容

进行扩容后elementData数组长度就变成了10

当添加第11个元素时,进行二次扩容

调用int newCapacity = oldCapacity + (oldCapacity>>1); 进行1.5倍扩容!
从而数组长度变成了15

public class ArrayList_1 {
public static void main(String[] args) {
//有参扩容机制,初始化指定容量大小
ArrayList list = new ArrayList(5);
for (int i = 0; i < 5; i++) {
list.add(i);
}
//进行第一次1.5倍扩容
list.add(6);
}
}

总结:
每次add都会检查数组容量,是否要进行扩容!
elementData数组默认为0,当进行第一次add进行第一次扩容,扩容大小为10,而后面进行二次扩容就是1.5倍扩容!
elementData数组默认为指定参数长度,第一次扩容时,1.5倍扩容!
Vector类和ArrayList类底层的结构一样也是数组!
不过和ArrayList区别就是,扩容策略不同,Vector是线程安全的(每个方法都加了synchronized),适用于多线程,而ArrayList线程不安全!
扩容策略


我们学习Vector构造方法后,发现Vector有个构造器,可以设置容量的增量!
可以自定义扩容的增量值!
通过下面的代码debug进行扩容机制的学习!
public class Vector_ {
public static void main(String[] args) {
//Vector无参扩容机制!
Vector vector = new Vector();
//一次扩容
for (int i = 0; i <10 ; i++) {
vector.add(i);
}
//进行二次扩容
vector.add(10);
}
}
无参构造器,初始化容量为10

第一次扩容

有参扩容机制和无参扩容机制类似,初始化时指定数组长度!扩容策略一样!
LinkedList类和上述2个不同,他的底层采用的是双向链表的方式存储数据

可以看到LinkedList实现了List接口和DeQue接口!

Node节点

这里通过frist保存头Node节点,last保存尾节点!
因为LinkedList实现了Deque双端队列接口,所以其下的方法都实现了

方法使用
package list;
import java.util.Arrays;
import java.util.LinkedList;
public class LinkedList_ {
public static void main(String[] args) {
LinkedList linkedList = new LinkedList();
linkedList.add(1);
linkedList.addLast(2);
linkedList.addFirst(0);
System.out.println("获取队首元素:"+linkedList.getFirst());
System.out.println("获取队尾元素:"+linkedList.getLast());
System.out.println(Arrays.toString(linkedList.toArray()));
System.out.println("出队:"+linkedList.poll());
System.out.println(Arrays.toString(linkedList.toArray()));
System.out.println("对尾删除元素:"+linkedList.pollLast());
linkedList.push(12);
linkedList.pop();
System.out.println(Arrays.toString(linkedList.toArray()));
}
}

注意:
这里的方法有点多:
offer/pollpush/popadd/remove
这里只有push/pop不能进行First/Last组合,其他都可!
public static void main(String[] args) {
LinkedList<Integer> list = new LinkedList<>();
list.add(1);
list.remove();
list.get(1);
}
add添加节点
默认队尾入队

remove删除节点
默认删除第一个节点!

get方法获取节点

| 底层结构 | 增删效率 | 改查效率 | |
|---|---|---|---|
| ArrayList/Vector | 可变数组 | 较低,要扩容 | 较高 |
| LinkedList | 双向链表 | 较高,通过链表修改指针即可 | 较低 |
三者如何抉择: