List 接口下面主要有两个实现ArrayList 和LinkedList,他们都是有顺序的,也就是放进去是什么顺序,取出来还是什么顺序,也就是基于线性存储,可以看作是一个可变数组
ArrayList:查询数据比较快,添加和删除数据比较慢(基于可变数组)
LinkedList:查询数据比较慢,添加和删除数据比较快(基于链表数据结构)
Vector:Vector 已经不建议使用,Vector 中的方法都是同步的,效率慢,已经被 ArrayList取代
Stack 是继承Vector 实现了一个栈,栈结构是后进先出,目前已经被LinkedList 取代
1 List接口
List集合存储元素的特点:有序可重复
List既然是Collection的子接口,肯定也有自己的特有方法。
特有常用方法:
void add(int index,Object element);
Object get(int index);
int indexOf(Object o);
int LastIndexOf(Object o);
Object remove(int index);
Object set(int index,Object element);
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
public class ListTest01 {
public static void main(String[] args) {
//创建集合对象
List mylist = new LinkedList();
//默认向集合尾部添加元素
mylist.add("a");
mylist.add("b");
mylist.add("c");
mylist.add("c");
mylist.add("d");
mylist.add("d");
//在下标为1的地方加入元素
//效率较低,用的较少
mylist.add(1, "hello");
//使用迭代器迭代集合
Iterator it = mylist.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//根据下标获取元素
System.out.println(mylist.get(2));//b
//因为有下标,所以List集合有自己比较特殊的遍历方式
//通过下标遍历。【List集合特有方式,Set没有。】
for (int i = 0; i < mylist.size(); i++) {
System.out.println(mylist.get(i));
}
//获取指定对象第一次出现的索引
System.out.println(mylist.indexOf("c"));//3
//获取指定对象最后一次出现的索引
System.out.println(mylist.lastIndexOf("d"));//6
//删除指定下标位置的元素
System.out.println(mylist.remove(0));
System.out.println(mylist.size());
//修改指定位置的元素
Object o = mylist.set(3, "hhh");
for (int i = 0; i < mylist.size(); i++) {
System.out.println(mylist.get(i));
}
}
}
1.1 ArrayList集合
ArrayList集合初始化容量是10(底层先创建了一个长度为0的数组,当添加第一个元素的时候,初始化容量为10);
ArrayList集合底层结构是Object数组;
构造方法:
new ArrayList();
new ArrayList(20);
ArrayList集合的扩容:
原容量的1.5倍。尽可能少的扩容。因为数组扩容效率较低,建议在使用ArrayList集合的时候预估计元素的个数,给定一个初始化容量。
数组优点:检索效率比较高。
数组缺点:随机增删元素效率比较低。数组无法存储大数据量。
向数组末尾添加元素,效率很高,不受影响。
ArrayList集合是非线程安全的。
面试问题:这么多集合中,你用哪个集合最多?
ArrayList集合。因为往数组末尾添加元素不受影响,检索元素某个元素操作比较多。
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
public class ArrayListTest02 {
public static void main(String[] args) {
//默认初始化容量10
List mylist = new ArrayList();
//指定初始化容量20
List mylist1 = new ArrayList(20);
Collection c = new HashSet();
c.add(12);
c.add(23);
c.add(34);
//通过构造方法将HashSet集合转换为List集合
List mylist2 = new ArrayList(c);
for (int i = 0; i < mylist2.size(); i++) {
System.out.println(mylist2.get(i));
}
}
}
1.1.1 ArrayList集合操作
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
*ArrayList集合特点:有序,可重复
*/
public class ArrayListTest {
public static void main(String[] args) {
//创建ArrayList集合
List<Integer> mylist = new ArrayList<>();
//添加元素
mylist.add(12);
mylist.add(23);
mylist.add(22);
mylist.add(45);
//取元素
System.out.println(mylist.get(0));
//下标遍历集合
for (int i = 0; i < mylist.size(); i++) {
System.out.println(mylist.get(i));
}
//foreach遍历
for (Integer i : mylist) {
System.out.println(i);
}
//迭代器遍历,所有的Collection都能用
Iterator it = mylist.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
1.2 LinkedList集合
单链表中的节点。
节点是单向链表中基本的单元。
每一个节点Node都有两个属性:
一个属性:是存储的数据。
另一个属性:是存储下一个节点的内存地址。
链表优点:随机增删元素效率较高。(因为增删元素不涉及大量元素位移)
链表缺点:查询效率较低,每一次查找某个元素的时候都需要从头节点开始往下遍历。
双向链表:基本单元还是节点Node。
ListedList集合没有初始化容量,最初这个链表中没有任何元素。first和lat引用都是null。
用法与ArrayList相同。
1.2.1 LinkedList集合操作
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
/**
* LinkedList特点:有序,可重复
*/
public class LinkeListTest {
public static void main(String[] args) {
//创建LinkeList集合
List<String> mylist = new LinkedList<>();
//添加元素
mylist.add("jack");
mylist.add("rose");
mylist.add("Lee");
mylist.add("Tom");
mylist.add("张三");
//取元素
System.out.println(mylist.get(3));
//删除元素
System.out.println(mylist.remove(3));
//遍历集合
//使用下标
for (int i = 0; i < mylist.size(); i++) {
System.out.println(mylist.get(i));
}
//使用迭代器
Iterator<String> it = mylist.iterator();
while (it.hasNext()) {
System.out.println(it.next());
}
//使用foreach
for (String s : mylist) {
System.out.println(s);
}
}
}
1.3 Vector集合
Vector:
底层也是数组
初始化容量10
扩容之后是原容量的2倍
Vector中所有的方法都是线程同步的,都带有synchronized关键字,是线程安全的。效率较低,使用较少。