Java Map 集合与 Collections 工具类全解析

在 Java 集合框架中,Map 作为双列集合的核心代表,专注于 “键值对” 数据的存储与管理;而 Collections 工具类则为集合操作提供了丰富的便捷方法。本文将结合实战代码,全面梳理 Map 集合的特性、用法,以及可变参数和 Collections 工具类的核心功能,助力高效处理集合数据。

一、Map 集合:双列集合的核心,键值对的管理专家

Map 集合与之前学习的 Set、List 等单列集合不同,其核心是 “键(Key)- 值(Value)” 的映射关系,适用于需要通过唯一标识查找数据的场景(如字典、配置表等)。

1. Map 集合的核心特性

根据LearnMap.java的定义,Map 的核心特性可总结为四点,这是理解 Map 的基础:

  1. 双列存储:一次需存储一对数据(键和值),键与值一一对应;
  1. 键唯一:键不能重复,若添加重复键,新值会覆盖旧值;
  1. 值可重复:不同键可对应相同的值;
  1. 键值对对象:每一组键值对在 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. 可变参数的注意事项

  1. 参数类型统一:可变参数只能接收同类型的参数,不能混合接收不同类型;
  1. 避免歧义:若方法重载时存在可变参数,需确保调用时不会产生歧义;
  1. 空参数处理:若未传递任何参数,可变参数会被视为长度为 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

五、核心知识点总结

  1. Map 集合:双列存储键值对,键唯一、值可重复,常用 HashMap 实现,遍历方式有 “键找值”“键值对遍历”“Lambda 遍历” 三种;
  1. 可变参数:语法为类型... 名称,底层是数组,解决参数个数不确定问题,需放在参数列表最后;
  1. Collections 工具类:提供批量添加、排序、打乱、二分查找等便捷方法,可简化集合操作,同时支持将集合转为线程安全类型。

掌握 Map 集合的键值对管理逻辑,结合可变参数的灵活性与 Collections 工具类的高效性,能大幅提升 Java 集合开发的效率与代码质量。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值