目录
ArrayList、LinkedList、Vector三者的相同之处
ArrayList、LinkedList、Vector源码分析
List接口概述
鉴于 Java 中数组用来存储数据的局限性,我们通常使用 List 替代数组
List 集合类中元素有序、且可重复,集合中的每个元素都有其对应的顺序索引,可以根据索引存取对应元素
List接口架构
Collection 接口:单列集合,用来存储一个一个的对象
List 接口:存储有序的、可重复的数据(“动态” 数组)
ArrayList:作为 List 接口的主要实现类,线程不安全但是效率高,底层使用 Object[ ] elementData 存储
LinkedList:对于频繁的插入、删除操作,使用此类效率比 ArrayList 高,底层使用双向 链表存储
Vector:作为 List 接口的古老实现类,线程安全但效率低,底层使用 Object[ ] elementData 存储
ArrayList、LinkedList、Vector三者的相同之处
三个类都实现了 List 接口,存储数据特点相同:存储有序的、可重复的数据
ArrayList、LinkedList、Vector源码分析
ArrayList的源码分析
JDK 8.0 之前
ArrayList list = new ArrayList ( ); // 底层创建了长度是 10 的 Object [ ] 数组 elementData
list . add (123); // elementData [0] = new Integer (123);
如果添加元素导致底层 elementData 数组容量不够,则扩容。默认情况下,扩容为原来的 1.5 倍,同时需要将原有的数组中的数据复制到新的数组中
综上,建议开发中使用带参的构造器:ArrayList list = new ArrayList (int capacity);
JDK 8.0 及之后
ArrayList list = new ArrayList ( ); // 底层 Object [ ] elementData 初始化为 { },并没有创建长度为 10 的数组
list . add (123); // 第一次调用 add()时,底层才创建长度为 10 的数组,并将数据添加到 elementData
综上,JDK 7.0 中的 ArrayList 的对象的创建类似于单例的饿汉式,而JDK 8.0 及之后的 ArrayList 的对象的创建类似于单例的懒汉式,延迟了数组的创建,节省内存
LinkedList的源码分析
LinkedList list = new LinkedList ( ); // 内部声明了 Node 类型的 first 和 last 属性,默认值为 null
list . add (123); // 将数据封装到 Node 中,创建了 Node 对象
Vector的源码分析
JDK 7.0 和 JDK 8.0 及之后通过 Vector()构造器创建对象时,底层都创建了长度为 10 的数组
如果添加元素导致底层 elementData 数组容量不够,则扩容。默认情况下,扩容为原来的 2 倍,同时需要将原有的数组中的数据复制到新的数组中
List接口中的方法
List 除了从 Collection 集合继承的方法外,List 集合里添加了一些根据索引来操作集合元素的方法
void add(int index, Object ele) | 在 index 位置插入 ele 元素 |
boolean addAll(int index, Collection eles) | 从 index 位置开始将 eles 中的所有元素添加进来 |
Object get(int index) | 获取指定 index 位置的元素 |
int indexOf(Object obj) | 返回 obj 在集合中首次出现的位置 |
int lastIndexOf(Object obj) | 返回 obj 在当前集合中末次出现的位置 |
Object remove(int index) | 移除指定 index 位置的元素,并返回此元素 |
Object set(int index, Object ele) | 设置指定 index 位置的元素为 ele |
List subList(int fromIndex, int toIndex) | 返回从 fromIndex 到 toIndex 位置的子集合 |
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ListTest {
@Test
public void test() {
ArrayList list = new ArrayList();
list.add(123);
list.add(456);
list.add("AA");
list.add(true);
// void add()
list.add(1,"BB");
System.out.println(list);
// boolean addAll()
List list1 = Arrays.asList(1,2,4);
list.addAll(list1);
System.out.println(list.size());
// Object get()
System.out.println(list.get(3));
//int indexOf() 如果元素不存在,返回 -1
int index = list.indexOf(4567);
System.out.println(index);
//int lastIndexOf()
System.out.println(list.lastIndexOf(456));
// Object remove()
Object obj = list.remove(0);
System.out.println(obj);
System.out.println(list);
// Object set()
list.set(1,"CC");
System.out.println(list);
// List subList()
List subList = list.subList(2,4);
System.out.println(subList);
System.out.println(list);
}
}
>>> [123, BB, 456, AA, true]
8
AA
-1
2
123
[BB, 456, AA, true, 1, 2, 4]
[BB, CC, AA, true, 1, 2, 4]
[AA, true]
[BB, CC, AA, true, 1, 2, 4]
有关List的面试题
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class MyTest {
@Test
public void test(){
List list = new ArrayList();
list.add(1);
list.add(2);
list.add(3);
updateList(list);
System.out.println(list);
}
private static void updateList(List list){
list.remove(2);
}
}
>>> [1, 2]
此时删除的是索引为 2 的元素,如果想删除元素 2 呢
list.remove(new Integer(2));
这样才可以删除元素 2