我们学习List下面ArrayList,LinkedList,Vector
类即可!
学习的重点就是了解他们的底层结构,扩容原理,通过源码进行学习!
@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维护了一个elementData
数组,由transient
修饰不可序列化!
ArrayList扩容机制:
我们通过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数组长度就变成了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);
}
}
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
接口!
这里通过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/poll
push/pop
add/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添加节点
默认队尾入队
默认删除第一个节点!
底层结构 | 增删效率 | 改查效率 | |
---|---|---|---|
ArrayList/Vector | 可变数组 | 较低,要扩容 | 较高 |
LinkedList | 双向链表 | 较高,通过链表修改指针即可 | 较低 |
三者如何抉择: