c260731courseLinkedList 是 Java 集合框架中功能最「全面」的实现类之一,它同时实现了多个接口:
List<E> 接口 —— 列表(线性表),有序、可重复、带索引Queue<E> 接口 —— 队列,先进先出(FIFO)Deque<E> 接口 —— 双端队列(Double Queue),两端都可以入队 / 出队同一个 LinkedList 对象,可以用不同的接口类型去引用。声明类型不同,「看得见」的方法就不同——这是接口多态(编译看左边:接口类型决定可用方法;运行看右边:真实对象是 LinkedList)。
| 声明类型 | 语义 | 可见的核心方法 |
|---|---|---|
LinkedList<Object> |
最全的方法集合(链表本体) | 链表 + List + Queue + Deque 全部方法 |
List<Object> |
列表线性表 | add/get/set/remove、indexOf、contains 等 |
Queue<Object> |
队列(FIFO) | offer 入队、poll 出队、peek 查看队头 |
Deque<Object> |
双端队列 | addFirst/addLast、pollFirst/pollLast、peekFirst/peekLast、push/pop(栈) |
// 来源:course/Demo01.java
package course;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class Demo01 {
public static void main(String[] args) {
// 使用最全的方法 --- 链表
LinkedList<Object> list = new LinkedList<>();
// 如果想使用 List 的方法 --- 列表线性表
List<Object> list1 = new LinkedList<>();
// 如果想使用队列 --- Queue
Queue<Object> queue = new LinkedList<>();
// 如果想使用双端队列 --- Double Queue
Deque<Object> deque = new LinkedList<>();
}
}
new LinkedList<>() 创建的是同一个对象,但可以赋予 List、Queue、Deque 三种「身份」。Queue 引用时只能调用队列方法(如 offer/poll/peek),无法调用 get(int) 这类 List 方法——把能力「收窄」到所需范围。Queue/Deque 引用 LinkedList,语义更清晰,也方便后续替换实现类。由于 Collection 集合接口继承了 Iterable 接口,所以我们使用的所有单列集合都具备 Iterable 的方法(iterator()),并且各个实现类都重写了它。
iterator() 方法获取该集合对应的迭代器对象(Iterator<E>)Set、LinkedList)| 方法 | 返回值 | 说明 |
|---|---|---|
boolean hasNext() |
boolean |
判断迭代器是否还有下一个元素 |
E next() |
E |
返回下一个元素,并把指针向后移动一位 |
void remove() |
void |
从集合中移除上次 next() 返回的元素(可选操作) |
迭代器内部有一个指针,初始位置在第一个元素之前:
[元素1] → [元素2] → [元素3] → [元素4] … → null
↑
iterator 初始位置(第一个元素之前)
hasNext():判断指针后是否还有元素next():取出当前元素并把指针后移// 来源:course/Demo02.java
package course;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedList;
public class Demo02 {
/*
由于Collection集合接口继承了Iterable接口
所以我们使用的所有的单列集合,都具有Iterable的方法,并且重写了方法
*/
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("元素1");
list.add("元素2");
// ... 共添加10个元素
// 方式一:我们遍历集合 —— for + 索引(ArrayList 有索引才支持)
for (int i = 0; i < list.size(); i++) {
System.out.println(list.get(i));
}
// 方式二:通过迭代器进行迭代遍历
Iterator<String> iterator = list.iterator(); // 通过集合对象获取它对应的迭代器对象
while (iterator.hasNext()) { // 判断迭代器有没有下一个元素,有就继续
String element = iterator.next(); // 通过迭代器对象获取下一个元素
System.out.println(element);
}
// 创建字符串泛型的 LinkedList 集合
LinkedList<String> list1 = new LinkedList<>();
// 添加10个元素 ...
// LinkedList 同样可以使用迭代器(链表没有索引,for+get 效率低)
Iterator<String> iterator1 = list1.iterator();
while (iterator1.hasNext()) {
String s = iterator1.next();
System.out.println(s);
}
}
}
Iterator<E> it = 集合对象.iterator(); // 1. 获取迭代器
while (it.hasNext()) { // 2. 判断是否有下一个
E e = it.next(); // 3. 获取下一个元素并后移指针
// 处理元素
}
next() 只能向后,不能回退。next() 会移动指针,多次调用 next() 会跳过元素。add/remove),会抛出 ConcurrentModificationException(快速失败机制)。单列集合(Collection 体系) 双列集合(Map 体系)
Iterable<E> ───────────── Map<K,V> 接口(键值对)
│ │
Collection<E> ── 并行存在 ──> HashMap<K,V>(最常用实现类)
├── List<E> —— 列表:有序、可重复、带索引
│ ├── ArrayList<E> —— 数组结构,随机访问快
│ └── LinkedList<E> —— 双链表结构,插入删除快
├── Queue<E> —— 队列:先进先出(FIFO)
│ └── Deque<E> —— 双端队列(LinkedList 实现)
└── Set<E> —— 集合:不可重复
LinkedList<E>
│
┌─────────────┼─────────────┐
▼ ▼ ▼
List<E> Queue<E> Deque<E>
(线性表) (队列FIFO) (双端队列/栈)
所以代码中才能写出:
List<Object> list1 = new LinkedList<>();
Queue<Object> queue = new LinkedList<>();
Deque<Object> deque = new LinkedList<>();
| 方式 | 适用场景 | 示例 |
|---|---|---|
for + size() + get(i) |
有索引的 List(ArrayList 效率高) | for (int i = 0; i < list.size(); i++) |
| Iterator 迭代器 | 所有单列集合(通用方式) | while (it.hasNext()) { it.next(); } |
| 增强 for(foreach) | 所有集合与数组(底层也是迭代器) | for (String s : list) |
Map 集合是一个接口,属于双列集合,与单列集合(Collection)并行存在:
public interface Map<K, V>
K 代表 Key(键) 的类型,V 代表 Value(值) 的类型<Key, Value>)HashMap创建 HashMap 对象有两种方式:
Map<String,Object> map = new HashMap<>(); // 方式一:接口多态,左边声明为 Map 接口
HashMap<String,Object> map1 = new HashMap<>(); // 方式二:直接用实现类
| 方法 | 说明 |
|---|---|
V put(K key, V value) |
向 Map 集合中添加元素(键值对) |
V get(Object key) |
根据 Key 键获取 Value 值 |
Set<K> keySet() |
把当前 Map 集合中的所有 Key 组成一个 Set 集合(无序的单列集合) |
Collection<V> values() |
把所有的 Value 值组合成一个单列集合 |
Set<Map.Entry<K,V>> entrySet() |
返回一个单列 Set 集合,集合中每个元素都是一个 Map 的内部类(Entry)对象,即由 Map 的键值对组成的一个类型 |
// 来源:course/Demo03.java
package course;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Demo03 {
public static void main(String[] args) {
Map<String,Object> map = new HashMap<>();
map.put("id","x1001");
map.put("name","张三");
map.put("age",25);
map.put("gender","男");
Collection<Object> values = map.values(); // 获取所有值
System.out.println(values); // [男, 张三, x1001, 25](无序,顺序≠添加顺序)
Set<String> set = map.keySet(); // 获取所有键
System.out.println(set); // [gender, name, id, age]
HashMap<String,Object> map1 = new HashMap<>();
map1.put("x001","张三");
map1.put("x002","李四");
map1.put("x003","王五");
map1.put("x004","赵六");
System.out.println(map1.values()); // [李四, 王五, 赵六, 张三]
System.out.println(map1.keySet()); // [x004, x003, x002, x001]
System.out.println(map1); // 直接打印:{x004=赵六, x003=王五, x002=李四, x001=张三}
}
}
put 会覆盖旧值;不同 Key 可以对应相同 Value。核心步骤:
LinkedList<Object> 对象LinkedList、List、Queue、Deque 四种类型引用它思考:
Queue 引用时,能否调用 get(int)?—— 不能,编译错误,Queue 接口中没有该方法push/pop(栈)和 addFirst/addLast(双端队列)核心步骤:
ArrayList<String>,添加 10 个元素for + get(i) 遍历iterator() 获取迭代器,while (hasNext()) + next() 遍历LinkedList<String> 执行同样的迭代器遍历思考:
hasNext() 和 next() 分别做什么?—— 判断是否存在下一个元素 / 取出下一个元素并移动指针for + get(i) 效率低?—— 每次 get(i) 都要从头遍历节点,时间复杂度 O(n),而迭代器沿链表逐个移动只需 O(1)核心步骤:
HashMap<String,Object>,用 put() 添加一组学生信息(id / name / age / gender)keySet() 获取所有键(返回 Set<String>)values() 获取所有值(返回 Collection<Object>)map 观察 HashMap 的无序特性思考:
keySet() 返回 Set?—— 键不可重复,正好符合 Set 的不可重复特性| 前置知识 | 当前知识 | 后续知识 |
|---|---|---|
| ArrayList 底层原理(0729) | LinkedList 多接口形态(List/Queue/Deque) | ListIterator(双向迭代) |
| LinkedList 双链表理论(0730) | Iterator 迭代器 | 增强 for / forEach 方法 |
| 泛型与集合体系(0729) | Iterable → Collection 继承体系 | Set 集合与 Map 迭代 |
| Collection 单列集合体系 | Map 集合 / HashMap 入门 | Map 遍历(entrySet)、HashMap 底层哈希表 |