一.List
在 Java 中,List 是一个接口,属于 java.util 包,是 Java 集合框架(Java Collections Framework)的重要组成部分。List(列表)是一种有序 的集合,它允许存储重复的元素。你可以把它想象成一个排队列表或者购物清单:
- 有序:你添加元素的顺序就是它们存储的顺序。
- 可重复:你可以添加多个相同的元素(比如买了两个苹果)。
- 通过索引访问:就像数组一样,可以通过下标(从 0 开始)来获取元素。
- 动态容量:实现类(如 ArrayList)会自动扩容,无需手动指定大小。
最常用的实现类是 ArrayList
注意:List 是接口,不能直接实例化。应使用接口引用 + 实现类实例的方式,例如
java
List<String> list = new ArrayList<>();
代码例子:一个简单的待办事项列表
java
import java.util.ArrayList;
import java.util.List;
public class ListDemo {
public static void main(String[] args) {
// 1. 创建 List
// 这里我们创建一个存储 String (字符串) 的列表
List<String> todoList = new ArrayList<>();
// 2. 添加数据 (add)
todoList.add("买牛奶"); // 索引 0
todoList.add("写Java代码"); // 索引 1
todoList.add("跑步"); // 索引 2
// 在指定位置插入元素 (例如在索引 1 的位置插入,原来的元素后移)
todoList.add(1, "回复邮件");
// 现在列表顺序: ["买牛奶", "回复邮件", "写Java代码", "跑步"]
System.out.println("--- 初始列表 ---");
System.out.println(todoList);
// 3. 获取数据 (get)
// 注意:索引从 0 开始
String firstTask = todoList.get(0);
System.out.println("第一个任务 is: " + firstTask); // 输出: 买牛奶
// 4. 修改数据 (set)
// 将索引为 2 的元素修改为 "学习Python"
todoList.set(2, "学习Python");
System.out.println("--- 修改后 ---");
System.out.println(todoList); // 输出: [买牛奶, 回复邮件, 学习Python, 跑步]
// 5. 删除数据 (remove)
// 方式 A: 根据索引删除
todoList.remove(0); // 删除第一个元素 "买牛奶"
// 方式 B: 根据对象内容删除 (删除第一个匹配到的 "跑步")
todoList.remove("跑步");
System.out.println("--- 删除后 ---");
System.out.println(todoList); // 输出: [回复邮件, 学习Python]
// 6. 检查是否存在 (contains)
boolean hasJava = todoList.contains("写Java代码");
System.out.println("还有写Java代码这个任务吗? " + hasJava); // 输出: false (因为之前被替换了)
// 7. 获取大小 (size)
System.out.println("当前任务数量: " + todoList.size()); // 输出: 2
// 8. 遍历 List (三种常用方式)
System.out.println("--- 遍历所有任务 ---");
// 方式 A: 传统 for 循环 (通过索引)
for (int i = 0; i < todoList.size(); i++) {
System.out.println("任务 " + (i + 1) + ": " + todoList.get(i));
}
// 方式 B: 增强 for 循环 (foreach) - **最推荐,简洁**
for (String task : todoList) {
System.out.println("正在做: " + task);
}
// 方式 C: forEach + Lambda (Java 8+)
todoList.forEach(task -> System.out.println("Lambda: " + task));
}
}
| 操作 | 方法 | 说明 |
|---|---|---|
| 创建 | new ArrayList<>() | 创建一个空的动态数组列表 |
| 添加 | add(element) | 在末尾添加元素 |
| 插入 | add(index, element) | 在指定索引位置插入元素 |
| 获取 | get(index) | 根据索引获取元素 |
| 修改 | set(index, element) | 替换指定索引位置的元素 |
| 删除 | remove(index) 或 remove(object) | 根据索引或删除第一个匹配的对象 |
| 判断存在 | contains(object) | 判断列表中是否包含某个元素 |
| 大小 | size() | 获取列表中元素的数量 |
| 清空 | clear() | 删除所有元素 |
注意事项
- 索引从 0 开始:这和数组一样。如果有 3 个元素,索引分别是 0, 1, 2。如果你尝试 get(3),会抛出IndexOutOfBoundsException(下标越界异常)。
- 泛型:同样强烈建议使用泛型。List 表示这个列表只能存字符串。如果你尝试add(123),编译器会直接报错,防止运行时错误。
- ArrayList vs LinkedList :
ArrayList:底层是数组。查询快(通过索引直接定位),增删慢(中间插入/删除需要移动后续元素)。大多数情况下首选
ArrayList。 LinkedList:底层是链表。增删快,查询慢。只有在频繁在列表中间进行插入/删除操作时才考虑使用。 - 基本数据类型:和 Map 一样,List 不能直接存 int, double 等基本类型,必须使用包装类 Integer, Double等。例如:List numbers = new ArrayList<>();
二.Map
在 Java 中,Map(映射)是一种存储 键值对 (Key-Value Pair) 的数据结构。是一种双列集合接口,你可以把它想象成一个字典或通讯录:
Key (键) :就像人的名字(唯一,用来查找)。
Value (值) :就像人的电话号码(对应的数据)。
最常用的实现类是 HashMap 。
核心特性:
- 键值对存储:每个元素由一个键(key)和一个值(value)组成。
- 键唯一:Map中不能包含重复的键;若尝试添加重复键,新值会覆盖旧值。
- 值可重复:多个键可以对应相同的值。
- 一对一映射:每个键最多对应一个值,体现数学中的函数概念
代码示例:一个简单的学生成绩表
java
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
// 1. 创建 Map
// Key 是 String (学生姓名), Value 是 Integer (分数)
Map<String, Integer> scoreMap = new HashMap<>();
// 2. 添加数据 (put)
scoreMap.put("张三", 90);
scoreMap.put("李四", 85);
scoreMap.put("王五", 92);
// 如果 key 已经存在,新的 value 会覆盖旧的
scoreMap.put("张三", 95); // 张三的分数从 90 变成了 95
System.out.println("--- 初始数据 ---");
System.out.println(scoreMap); // 输出: {张三=95, 李四=85, 王五=92}
// 3. 获取数据 (get)
int zhangSanScore = scoreMap.get("张三");
System.out.println("张三的分数是: " + zhangSanScore); // 输出: 95
// 如果 key 不存在,get 返回 null
Integer zhaoLiuScore = scoreMap.get("赵六");
System.out.println("赵六的分数是: " + zhaoLiuScore); // 输出: null
// 4. 检查是否存在 (containsKey / containsValue)
boolean hasLiSi = scoreMap.containsKey("李四");
System.out.println("是否有李四? " + hasLiSi); // 输出: true
// 5. 删除数据 (remove)
scoreMap.remove("王五");
System.out.println("--- 删除王五后 ---");
System.out.println(scoreMap); // 输出: {张三=95, 李四=85}
// 6. 遍历 Map (三种常用方式)
System.out.println("--- 遍历所有数据 ---");
// 方式 A: 遍历所有的 Key,然后通过 Key 获取 Value (最常用)
for (String name : scoreMap.keySet()) {
Integer score = scoreMap.get(name);
System.out.println("学生: " + name + ", 分数: " + score);
}
// 方式 B: 直接遍历 Entry (键值对对象),效率稍高
for (Map.Entry<String, Integer> entry : scoreMap.entrySet()) {
System.out.println("学生: " + entry.getKey() + ", 分数: " + entry.getValue());
}
}
}
核心知识点总结:
| 操作 | 方法 | 说明 |
|---|---|---|
| 创建 | new HashMap<>() | 创建一个空的 Map |
| 添加/修改 | put(key, value) | 如果 Key 不存在则添加;如果存在则覆盖旧值 |
| 获取 | get(key) | 根据 Key 获取 Value。如果 Key 不存在,返回 null |
| 删除 | remove(key) | 根据 Key 删除整个键值对 |
| 判断存在 | containsKey(key) | 判断是否包含某个 Key |
| 大小 | size() | 获取 Map 中有多少个键值对 |
| 清空 | clear() | 删除所有元素 |
注意事项
- Key 的唯一性:Map 中的 Key 必须是唯一的。如果你 put 了两个相同的 Key,后面的值会覆盖前面的值。
- Null 值:HashMap 允许 Key 和 Value 为 null(但 Key 为 null 只能有一个)。 调用 get() 时,如果返回null,可能是因为 Key 不存在,也可能是因为 Value 本身就是 null。建议先用 containsKey() 判断。
- 泛型<String, Integer>:强烈建议使用泛型指定 Key 和 Value的类型,这样编译器会在写代码时就帮你检查类型错误,避免运行时出错。
- 为什么用 Integer 而不是 int?:因为 Map 的Value 必须是对象(Object),int 是基本数据类型,不能直接放入 Map。Java 会自动装箱(Auto-boxing)将int 转为 Integer,所以你可以直接写 put("张三", 90),编译器会自动处理。