在 Java 集合框架中,Map 作为双列集合的核心代表,专注于 “键值对” 数据的存储与管理;而 Collections 工具类则为集合操作提供了丰富的便捷方法。本文将结合实战代码,全面梳理 Map 集合的特性、用法,以及可变参数和 Collections 工具类的核心功能,助力高效处理集合数据。
一、Map 集合:双列集合的核心,键值对的管理专家
Map 集合与之前学习的 Set、List 等单列集合不同,其核心是 “键(Key)- 值(Value)” 的映射关系,适用于需要通过唯一标识查找数据的场景(如字典、配置表等)。
1. Map 集合的核心特性
根据LearnMap.java的定义,Map 的核心特性可总结为四点,这是理解 Map 的基础:
- 双列存储:一次需存储一对数据(键和值),键与值一一对应;
- 键唯一:键不能重复,若添加重复键,新值会覆盖旧值;
- 值可重复:不同键可对应相同的值;
- 键值对对象:每一组键值对在 Java 中被封装为Map.Entry对象,便于整体操作。
2. Map 的常用实现类
Map 是接口,需通过实现类实例化,常用实现类有三个,特性各有侧重:
- HashMap:基于哈希表实现,键无序、唯一,查询效率高(时间复杂度接近 O (1)),线程不安全,是日常开发的首选;
- LinkedHashMap:HashMap 的子类,底层增加双向链表,键的顺序与添加顺序一致,兼顾顺序与性能;
- TreeMap:基于红黑树实现,键可排序(自然排序或自定义排序),适用于需按键排序的场景。
本文以最常用的HashMap为例展开讲解,其他实现类的 API 用法基本一致。
3. Map 集合的常用 API
LearnMap.java演示了 Map 的核心 API,涵盖添加、删除、查询等基础操作,具体如下:
(1)基本操作:添加、删除与判断
// 1. 创建Map对象(键为String类型,值为String类型)
Map<String, String> map = new HashMap<>();
// 2. 添加元素:put(K key, V value)
// 细节:键不存在时,添加键值对,返回null;键存在时,新值覆盖旧值,返回旧值
map.put("张三", "河南"); // 添加成功,返回null
map.put("李四", "杭州");
map.put("张三", "北京"); // 键"张三"已存在,覆盖旧值"河南",返回"河南"
// 3. 删除元素
map.remove("李四"); // 根据键删除键值对,返回被删除的值"杭州"
// map.clear(); // 清空所有键值对
// 4. 判断操作
boolean hasZhang = map.containsKey("张三"); // 判断是否包含指定键:true
boolean hasHenan = map.containsValue("河南"); // 判断是否包含指定值:false(已被覆盖)
boolean isEmpty = map.isEmpty(); // 判断是否为空:false
int size = map.size(); // 获取键值对个数:1(仅"张三"-"北京")
// 打印集合:默认输出格式为 {键1=值1, 键2=值2, ...}
System.out.println(map); // 输出:{张三=北京}
4. Map 集合的三种遍历方式
Map 无索引,遍历方式与单列集合不同,LearnMap.java提供了三种核心遍历方案,覆盖不同使用场景:
(1)方式一:键找值(最常用)
先获取所有键的集合,再通过键遍历获取对应的值,步骤清晰,易于理解:
// 1. 获取所有键的Set集合(键唯一,故用Set存储)
Set<String> keys = map.keySet();
// 2. 遍历键集合,通过键获取值
// 增强for循环遍历
for (String key : keys) {
String value = map.get(key); // 根据键获取值
System.out.println(key + "=" + value);
}
// Lambda表达式遍历键集合
keys.forEach(key -> System.out.println(key + "=" + map.get(key)));
(2)方式二:键值对遍历(效率更高)
直接获取所有Map.Entry键值对对象,同时获取键和值,减少一次get(key)的查询开销,效率更优:
// 1. 获取所有键值对对象的Set集合
Set<Map.Entry<String, String>> entries = map.entrySet();
// 2. 遍历键值对集合
for (Map.Entry<String, String> entry : entries) {
String key = entry.getKey(); // 获取键
String value = entry.getValue(); // 获取值
System.out.println(key + "=" + value);
}
// Lambda表达式遍历键值对集合
entries.forEach(entry -> System.out.println(entry.getKey() + "=" + entry.getValue()));
(3)方式三:Lambda 表达式遍历(最简洁)
Java 8 及以上版本支持通过forEach(BiConsumer<? super K, ? super V> action)方法直接遍历,代码最简洁:
// 直接传递Lambda表达式,参数依次为键和值
map.forEach((key, value) -> System.out.println(key + "=" + value));
二、可变参数:灵活处理不确定个数的方法参数
在LearnVariableElement.java中,可变参数解决了 “方法参数个数不固定” 的问题,使方法能灵活接收任意个数的同类型参数。
1. 可变参数的定义与语法
可变参数允许方法的形参个数动态变化,语法格式为:
修饰符 返回值类型 方法名(参数类型... 参数名) {
// 方法体
}
核心特点:
- 底层本质是数组,方法内部可将可变参数当作数组处理;
- 一个方法中只能有一个可变参数;
- 若方法有多个参数,可变参数必须放在最后。
2. 可变参数的使用示例
// 定义可变参数方法,接收任意个数的int类型参数
public static int getSum(int... args) {
int sum = 0;
// 可变参数本质是数组,可通过增强for循环遍历
for (int arg : args) {
sum += arg;
}
return sum;
}
// 调用可变参数方法:可传递任意个数的参数,甚至直接传递数组
public static void main(String[] args) {
System.out.println(getSum(1, 2)); // 传递2个参数:输出3
System.out.println(getSum(1, 2, 3, 4)); // 传递4个参数:输出10
System.out.println(getSum(new int[]{5, 6, 7})); // 传递数组:输出18
}
3. 可变参数的注意事项
- 参数类型统一:可变参数只能接收同类型的参数,不能混合接收不同类型;
- 避免歧义:若方法重载时存在可变参数,需确保调用时不会产生歧义;
- 空参数处理:若未传递任何参数,可变参数会被视为长度为 0 的数组,不会出现空指针异常。
三、Collections 工具类:集合操作的 “瑞士军刀”
java.util.Collections是集合的工具类,提供了大量静态方法,用于简化集合的常见操作(如排序、打乱、拷贝等),LearnCollections.java演示了其部分核心功能。
1. Collections 的核心功能与 API
Collections 的方法覆盖集合操作的多个场景,以下是最常用的 API 及示例(基于LearnCollections.java扩展):
(1)批量添加元素:addAll(Collection<T> c, T... elements)
一次性向集合中添加多个元素,比多次调用add()更高效:
ArrayList<String> list = new ArrayList<>();
// 批量添加元素
Collections.addAll(list, "苹果", "香蕉", "橙子", "葡萄");
System.out.println(list); // 输出:[苹果, 香蕉, 橙子, 葡萄]
(2)打乱集合顺序:shuffle(List<?> list)
随机打乱 List 集合中元素的顺序,常用于抽奖、随机排序等场景:
Collections.shuffle(list);
System.out.println(list); // 输出示例:[香蕉, 葡萄, 苹果, 橙子](每次运行结果不同)
(3)排序集合:sort(List<T> list)与sort(List<T> list, Comparator<T> c)
- 自然排序:sort(List<T> list),要求集合元素实现Comparable接口(如 String、Integer 默认支持);
- 自定义排序:sort(List<T> list, Comparator<T> c),通过 Comparator 指定排序规则,更灵活。
示例:
// 自然排序(String按字典序升序)
Collections.sort(list);
System.out.println(list); // 输出:[苹果, 橙子, 香蕉, 葡萄](中文按Unicode排序)
// 自定义排序(按字符串长度降序)
Collections.sort(list, (s1, s2) -> s2.length() - s1.length());
System.out.println(list); // 输出:[苹果, 橙子, 香蕉, 葡萄](均为2个字符,顺序不变)
(4)二分查找:binarySearch(List<T> list, T key)
在已排序的 List 集合中查找指定元素,返回元素索引(未找到返回负数),效率远高于线性查找:
// 先排序(二分查找依赖有序集合)
Collections.sort(list);
// 查找"橙子"
int index = Collections.binarySearch(list, "橙子");
System.out.println("橙子的索引:" + index); // 输出:1
(5)其他常用方法
- 拷贝集合:copy(List<T> dest, List<T> src),将 src 集合的元素拷贝到 dest 集合(需确保 dest 容量≥src);
- 填充集合:fill(List<T> list, T obj),用指定元素覆盖集合中的所有元素;
- 最值获取:max(Collection<T> coll)/min(Collection<T> coll),获取集合中的最大 / 最小值;
- 交换元素:swap(List<?> list, int i, int j),交换集合中指定索引的两个元素。
示例:
// 填充集合
Collections.fill(list, "西瓜");
System.out.println(list); // 输出:[西瓜, 西瓜, 西瓜, 西瓜]
// 交换元素(交换索引0和2的元素)
Collections.swap(list, 0, 2);
System.out.println(list); // 输出:[西瓜, 西瓜, 西瓜, 西瓜](元素相同,无明显变化)
2. Collections 的线程安全方法
Collections 还提供了将非线程安全集合转为线程安全集合的方法,适用于多线程场景:
// 将ArrayList转为线程安全集合
List<String> safeList = Collections.synchronizedList(new ArrayList<>());
// 将HashMap转为线程安全集合
Map<String, String> safeMap = Collections.synchronizedMap(new HashMap<>());
四、实战综合案例:Map+Collections 的协同应用
结合 Map 的键值对存储与 Collections 的排序功能,实现 “学生成绩排名” 的需求:
1. 需求场景
存储学生姓名(键)与成绩(值),按成绩降序排序并输出排名。
2. 完整代码实现
import java.util.*;
public class MapCollectionsDemo {
public static void main(String[] args) {
// 1. 创建Map存储学生姓名与成绩
Map<String, Integer> scoreMap = new HashMap<>();
Collections.addAll(scoreMap,
"张三", 90,
"李四", 85,
"王五", 95,
"赵六", 80
);
// 2. 将键值对转为List,便于排序
List<Map.Entry<String, Integer>> scoreList = new ArrayList<>(scoreMap.entrySet());
// 3. 按成绩降序排序(自定义排序)
Collections.sort(scoreList, (e1, e2) -> e2.getValue() - e1.getValue());
// 4. 输出排名
System.out.println("=== 学生成绩排名 ===");
for (int i = 0; i < scoreList.size(); i++) {
Map.Entry<String, Integer> entry = scoreList.get(i);
System.out.println("第" + (i + 1) + "名:" + entry.getKey() + ",成绩:" + entry.getValue());
}
}
}
3. 运行结果
=== 学生成绩排名 ===
第1名:王五,成绩:95
第2名:张三,成绩:90
第3名:李四,成绩:85
第4名:赵六,成绩:80
五、核心知识点总结
- Map 集合:双列存储键值对,键唯一、值可重复,常用 HashMap 实现,遍历方式有 “键找值”“键值对遍历”“Lambda 遍历” 三种;
- 可变参数:语法为类型... 名称,底层是数组,解决参数个数不确定问题,需放在参数列表最后;
- Collections 工具类:提供批量添加、排序、打乱、二分查找等便捷方法,可简化集合操作,同时支持将集合转为线程安全类型。
掌握 Map 集合的键值对管理逻辑,结合可变参数的灵活性与 Collections 工具类的高效性,能大幅提升 Java 集合开发的效率与代码质量。
6万+

被折叠的 条评论
为什么被折叠?



