List、ArrayList、LinkedList、Vector
List是Collection的一个子接口,ArrayList、LinkedList、Vector是List的实现类。
它们的共同特点都是:有序、可重复。
它们拥有Collection集合的所有方法,也有一些自己特有的方法。
因为是有序的,即集合中的元素是有下标的,所以可以通过元素下标来操作元素。
如下:
(下标从0开始!)
-
void add(int index, E element):在指定位置添加元素;
-
E get(int index):获取指定位置的元素;
-
E remove(int index):移除指定位置的元素;
-
E set(int index,E element):将指定位置的元素替换成别的值;
1.List
List是一个接口,不能实例化对象,需要借助其实现子类。
由于List是有序的,所以在迭代器遍历和for增强遍历的基础上,还可以使用下标遍历。
package com.dh.list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class List01 {
public static void main(String[] args) {
//List是一个接口,需要借助其子类实例化对象
List list = new ArrayList();
list.add("a");
list.add("a");//可重复
list.add(1,"abc");//可在指定位置添加元素
System.out.println(list.get(2));//获取指定位置的元素
list.remove(2);//删除指定位置的元素
list.set(1,"c");//将指定位置的元素替换成别的值
//遍历
//1.迭代器
System.out.println("迭代器遍历:");
Iterator iterator = list.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
//2.因为有下标,所以可以通过下标遍历
System.out.println("通过for循环使用下标遍历:");
for (int i = 0; i <list.size() ; i++) {
System.out.println(list.get(i));
}
//3.foreach
System.out.println("for增强遍历:");
for (Object o : list) {
System.out.println(o);
}
}
}
2.ArrayList
ArrayList的底层是Object数组,是线程不安全的。
数组的特点:
- 优点:检索效率高。因为数组的内存空间是连续的,每个元素所占的空间大小也相同,知道首地址,就可以通过数学表达式计算出下标,通过下标获取元素。
- 缺点:随机增删元素效率低,因为涉及到元素的位移。(但是从末尾添加元素的效率是不低的);并且不能存储大容量数据,因为可能很难找到一个那么大的连续的内存空间。
查看ArrayList的源码,可以看到,有一个成员变量:
private static final int DEFAULT_CAPACITY = 10;
ArrayList的默认初始化容量为10(一开始是空数组,容量为0,当添加第一个元素时,就会初始化为10)。也可以通过构造方法自己确定初始化容量。
当元素满了之后,会自动扩容增长到1.5倍的容量。(是增长到)10->15->22.5->......
但是数组扩容的效率比较低,所以尽量避免扩容,最好在一开始就能预估出一个合适的容量。
方法和上述List使用相同。
List的构造方法可以将Set集合转变成List集合。
ArrayList集合是使用最多的,因为它的检索能力高,插入也一般都不会随机插入,一般都是在元素末尾插入,效率也不低。所以在实际开发中,ArrayList的使用是比较多的。
3.LinkedList
LinkedList的底层是双向链表。
链表的基本单元是节点Node,双向链表节点有三部分:存储的数据(Object element)、上一个元素数据的内存地址(Node pre)、下一个元素数据的内存地址(Node next)。
双向链表示意图:
双向链表的特点:
- 优点:随机增删元素效率高,因为不需要涉及大量元素的位移。
- 缺点:随机检索效率低,因为双向链表的内存地址不连续,每次都需要从双向链表的头节点开始遍历检索。
LinkedList有一些特殊的方法:以下列举的只是部分。
- void addFirst():将元素插入开头;
- void addLast():将元素插入结尾;
- E getFirst():获得第一个元素;
- E getLast():获得最后一个元素;
- E removeFirst():移除第一个元素;
- E removeLast():移除最后一个元素;
- E peekFirst():检索但不删除第一个元素;
- E peekLast():检索但不删除最后一个元素;
- E pollFirst():检索并删除第一个元素;
- E peekLast():检索并删除最后一个元素;
- E pop():从列表中弹出一个元素;
- void push(E e):将e放入此列表中。
方法的使用很简单,故在此不做过多赘述。
4.Vector
Vector的底层也是数组,但是Vector的线程安全的。但是效率比较低,现在使用比较少。
Vector的初始容量为10,扩容会增长到两倍。10->20->40->......
Collections工具类可以将线程不安全的集合转变成线程安全的集合。
Collections.synchronizedList(new ArrayList());
水平有限,若有错误望指出~