(一)Map 的定义和创建
Map 创建格式:
1.不可变 Map:val mapName: Map[KeyType, ValueType] = Map(key1 -> value1, key2 -> value2,...)
2.可变 Map(需导入scala.collection.mutable.Map):val mapName:
mutable.Map[KeyType, ValueType] = mutable.Map(key1 -> value2,...)
1. Map 的基本定义
不可变 Map(默认)
// 方式1:使用 -> 操作符
val map1 = Map("name" -> "Alice", "age" -> 25, "city" -> "Beijing")
// 方式2:使用元组形式
val map2 = Map(("name", "Alice"), ("age", 25), ("city", "Beijing"))
// 空Map
val emptyMap = Map.empty[String, Int]
可变 Map
import scala.collection.mutable.Map
// 创建可变Map
val mutableMap = Map("name" -> "Alice", "age" -> 25)
// 创建空的可变Map
val emptyMutableMap = Map.empty[String, Any]
2. Map 的创建示例
object MapExample {
def main(args: Array[String]): Unit = {
// 不可变Map
val student = Map(
"id" -> 1001,
"name" -> "张三",
"score" -> 95.5
)
println(s"不可变Map: $student")
// 可变Map
import scala.collection.mutable.Map
val mutableStudent = Map(
"id" -> 1002,
"name" -> "李四"
)
println(s"可变Map: $mutableStudent")
}
}
3. Map 的特性和规则
键的唯一性
val map = Map("a" -> 1, "b" -> 2, "a" -> 3) // 结果: Map(a -> 3, b -> 2)
println(map) // 后面的键值会覆盖前面的相同键
类型推断
// Scala会自动推断类型
val map1 = Map(1 -> "one", 2 -> "two") // Map[Int, String]
val map2 = Map("x" -> 1.0, "y" -> 2.0) // Map[String, Double]
4. 创建Map的不同方式
使用 apply 方法
val map1 = Map.apply("a" -> 1, "b" -> 2)
从其他集合转换
// 从List创建
val list = List(("a", 1), ("b", 2))
val mapFromList = list.toMap
// 从数组创建
val array = Array(("x", 10), ("y", 20))
val mapFromArray = array.toMap
使用 zip 方法
val keys = List("name", "age", "city")
val values = List("Alice", 25, "Beijing")
val zippedMap = keys.zip(values).toMap
5. 完整示例
object MapCreationDemo {
def main(args: Array[String]): Unit = {
// 1. 基本创建
val capitals = Map(
"China" -> "Beijing",
"Japan" -> "Tokyo",
"USA" -> "Washington"
)
println(s"首都映射: $capitals")
// 2. 可变Map创建
import scala.collection.mutable.Map
val shoppingCart = Map(
"apple" -> 3,
"banana" -> 5,
"orange" -> 2
)
println(s"购物车: $shoppingCart")
// 3. 空Map创建
val emptyImmutable = Map.empty[String, Int]
val emptyMutable = Map.empty[String, String]
println(s"空不可变Map: $emptyImmutable")
println(s"空可变Map: $emptyMutable")
// 4. 类型验证
println(s"capitals类型: ${capitals.getClass}")
println(s"shoppingCart类型: ${shoppingCart.getClass}")
}
}
6. 运行结果
首都映射: Map(China -> Beijing, Japan -> Tokyo, USA -> Washington)
购物车: Map(apple -> 3, banana -> 5, orange -> 2)
空不可变Map: Map()
空可变Map: Map()
capitals类型: class scala.collection.immutable.Map$Map3
shoppingCart类型: class scala.collection.mutable.HashMap
关键点总结
- 默认不可变:直接使用
Map()创建的是不可变Map - 键唯一性:相同的键会覆盖之前的值
- 类型安全:Scala有强大的类型推断能力
- 灵活创建:支持多种创建方式,包括从其他集合转换
可变 vs 不可变 Map 对比
| 特性 | 可变Map | 不可变Map |
|---|---|---|
| 包路径 | scala.collection.mutable.Map | scala.collection.immutable.Map |
| 修改方式 | 直接修改原Map | 创建新Map |
| 操作符 | +=, -= | +, - |
| 线程安全 | 不安全 | 安全 |
| 性能 | 修改操作快 | 修改需要复制 |
(二)Map 的常用方法 - 添加元素
可变 Map 的添加方法
import scala.collection.mutable.Map
object MapAddDemo {
def main(args: Array[String]): Unit = {
val scores = Map("Alice" -> 90, "Bob" -> 85)
// 1. 使用 += 添加单个元素
scores += ("Charlie" -> 95)
// 2. 使用 += 添加多个元素
scores += ("David" -> 88, "Eve" -> 92)
// 3. 使用 put 方法添加(返回Option)
val previousValue = scores.put("Alice", 96) // 更新Alice的分数
println(s"Alice原来的分数: $previousValue") // 输出: Some(90)
// 4. 使用 update 方法
scores.update("Frank", 87)
scores("Grace") = 93 // 等价于 update
// 5. 使用 ++= 添加另一个Map
val newScores = Map("Henry" -> 89, "Ivy" -> 91)
scores ++= newScores
println(s"添加后的Map: $scores")
}
}
不可变 Map 的添加方法
object ImmutableMapAdd {
def main(args: Array[String]): Unit = {
val original = Map("A" -> 1, "B" -> 2)
// 1. 使用 + 添加单个元素(返回新Map)
val withC = original + ("C" -> 3)
// 2. 使用 + 添加多个元素
val withMore = original + ("D" -> 4, "E" -> 5)
// 3. 使用 ++ 合并另一个Map
val additional = Map("F" -> 6, "G" -> 7)
val merged = original ++ additional
println(s"原Map: $original")
println(s"添加C后: $withC")
println(s"添加多个后: $withMore")
println(s"合并后: $merged")
}
}
(三)Map 的常用方法 - 查询元素
object MapQueryDemo {
def main(args: Array[String]): Unit = {
val student = Map(
"name" -> "张三",
"age" -> 20,
"score" -> 95.5,
"city" -> "北京"
)
// 1. 使用 get 方法(返回Option)
val nameOption = student.get("name")
println(s"姓名: $nameOption") // 输出: Some(张三)
// 2. 直接使用键访问(如果键不存在会抛出异常)
val age = student("age")
println(s"年龄: $age")
// 3. 使用 getOrElse 提供默认值
val gender = student.getOrElse("gender", "未知")
println(s"性别: $gender") // 输出: 未知
// 4. 使用 contains 检查键是否存在
if (student.contains("score")) {
println("成绩信息存在")
}
// 5. 使用 apply 方法(与直接访问相同)
val city = student.apply("city")
println(s"城市: $city")
// 6. 获取所有键和值
println(s"所有键: ${student.keys}")
println(s"所有值: ${student.values}")
println(s"键集合: ${student.keySet}")
// 7. 安全访问示例
val phone = student.get("phone") match {
case Some(value) => value
case None => "未提供"
}
println(s"电话: $phone")
}
}
(四)Map 的常用方法 - 删除元素(仅针对可变 Map)
import scala.collection.mutable.Map
object MapRemoveDemo {
def main(args: Array[String]): Unit = {
val mutableMap = Map(
"A" -> 1, "B" -> 2, "C" -> 3,
"D" -> 4, "E" -> 5, "F" -> 6
)
println(s"原始Map: $mutableMap")
// 1. 使用 -= 删除单个元素
mutableMap -= "A"
println(s"删除A后: $mutableMap")
// 2. 使用 -= 删除多个元素
mutableMap -= ("B", "C")
println(s"删除B,C后: $mutableMap")
// 3. 使用 remove 方法(返回被删除的值)
val removedValue = mutableMap.remove("D")
println(s"删除D, 返回值: $removedValue") // 输出: Some(4)
println(s"删除D后: $mutableMap")
// 4. 删除不存在的键(不会报错)
mutableMap -= "X" // 安全,不会报错
val noValue = mutableMap.remove("Y")
println(s"删除不存在的键Y: $noValue") // 输出: None
// 5. 使用 --= 删除多个键
val keysToRemove = Set("E", "F")
mutableMap --= keysToRemove
println(s"删除E,F后: $mutableMap")
// 6. 清空整个Map
mutableMap.clear()
println(s"清空后: $mutableMap")
}
}
(五)Map 的遍历
object MapTraversalDemo {
def main(args: Array[String]): Unit = {
val studentInfo = Map(
"name" -> "李四",
"age" -> 22,
"major" -> "计算机科学",
"score" -> 88.5,
"city" -> "上海"
)
println("=== 遍历方式1: foreach ===")
// 1. 使用 foreach 遍历
studentInfo.foreach { case (key, value) =>
println(s"键: $key, 值: $value")
}
println("\n=== 遍历方式2: for循环 ===")
// 2. 使用 for 循环遍历
for ((key, value) <- studentInfo) {
println(s"$key -> $value")
}
println("\n=== 遍历方式3: 只遍历键 ===")
// 3. 只遍历键
studentInfo.keys.foreach { key =>
println(s"键: $key")
}
println("\n=== 遍历方式4: 只遍历值 ===")
// 4. 只遍历值
studentInfo.values.foreach { value =>
println(s"值: $value")
}
println("\n=== 遍历方式5: 使用迭代器 ===")
// 5. 使用迭代器
val iterator = studentInfo.iterator
while (iterator.hasNext) {
val (key, value) = iterator.next()
println(s"$key: $value")
}
println("\n=== 遍历方式6: 带条件的遍历 ===")
// 6. 带条件的遍历
for ((key, value) <- studentInfo if key.startsWith("a")) {
println(s"以'a'开头的键: $key -> $value")
}
println("\n=== 遍历方式7: 转换后遍历 ===")
// 7. 转换后遍历
studentInfo.map { case (key, value) =>
s"${key.toUpperCase}: $value"
}.foreach(println)
}
}
完整综合示例
object MapCompleteDemo {
def main(args: Array[String]): Unit = {
import scala.collection.mutable.Map
// 创建可变Map
var inventory = Map(
"apple" -> 10,
"banana" -> 5,
"orange" -> 8
)
println("初始库存:")
inventory.foreach(println)
// 添加新商品
inventory += ("grape" -> 12)
println("\n添加葡萄后:")
inventory.foreach(println)
// 查询库存
println(s"\n苹果库存: ${inventory.getOrElse("apple", 0)}")
println(s"是否存在香蕉: ${inventory.contains("banana")}")
// 更新库存
inventory("apple") = 15
println(s"\n更新苹果库存后: ${inventory("apple")}")
// 删除商品
inventory -= "orange"
println("\n删除橙子后:")
inventory.foreach(println)
// 遍历并处理
println("\n库存报告:")
for ((item, quantity) <- inventory) {
val status = if (quantity > 10) "充足" else "需要补货"
println(s"商品: $item, 数量: $quantity, 状态: $status")
}
}
}
运行结果示例
初始库存:
(apple,10)
(banana,5)
(orange,8)
添加葡萄后:
(apple,10)
(banana,5)
(orange,8)
(grape,12)
苹果库存: 10
是否存在香蕉: true
更新苹果库存后: 15
删除橙子后:
(apple,15)
(banana,5)
(grape,12)
库存报告:
商品: apple, 数量: 15, 状态: 充足
商品: banana, 数量: 5, 状态: 需要补货
商品: grape, 数量: 12, 状态: 充足
Map 关键点总结
1. Map 的基本概念
- 键值对结构:每个键对应一个值,键是唯一的
- 两种类型:可变Map (
mutable.Map) 和不可变Map (immutable.Map) - 默认不可变:直接使用
Map()创建的是不可变Map
2. 创建方式
// 不可变Map(默认)
val map1 = Map("a" -> 1, "b" -> 2)
val map2 = Map(("a", 1), ("b", 2))
// 可变Map
import scala.collection.mutable.Map
val mutableMap = Map("x" -> 10, "y" -> 20)
3. 添加元素的关键区别
可变Map
map += ("c" -> 3) // 直接修改原Map
map.put("d", 4) // 返回Option[原值]
map("e") = 5 // 直接赋值
不可变Map
val newMap = map + ("c" -> 3) // 返回新Map,原Map不变
val merged = map1 ++ map2 // 合并Map
4. 查询元素的正确方式
安全查询(推荐)
val value = map.get("key") // 返回 Option[T]
val value = map.getOrElse("key", default) // 提供默认值
直接查询(危险)
val value = map("key") // 键不存在时抛出异常
检查存在性
if (map.contains("key")) { ... }
5. 删除元素的限制
仅可变Map支持删除
map -= "key" // 删除单个键
map -= ("a", "b") // 删除多个键
map.remove("key") // 返回被删除的值Option
map.clear() // 清空Map
不可变Map的"删除"
val newMap = map - "key" // 返回删除指定键后的新Map
6. 遍历的多种方式
// 遍历键值对
map.foreach { case (k, v) => ... }
// for循环遍历
for ((k, v) <- map) { ... }
// 分别遍历键和值
map.keys.foreach(...)
map.values.foreach(...)
7. 重要特性
键的唯一性
val map = Map("a" -> 1, "a" -> 2) // 结果: Map(a -> 2)
// 后面的键值会覆盖前面的相同键
类型安全
val map = Map("name" -> "Alice", "age" -> 25)
// Scala自动推断为 Map[String, Any]
性能特点
- 查找高效:基于哈希表,平均O(1)时间复杂度
- 无序性:不保证元素的顺序(LinkedHashMap除外)
8. 使用场景建议
使用可变Map当:
- 需要频繁增删改操作
- 在单线程环境下
- 对性能要求较高
使用不可变Map当:
- 数据基本不变
- 多线程环境
- 函数式编程风格
- 需要保证数据一致性
9. 线程安全考虑
- 不可变Map:天然线程安全
- 可变Map:非线程安全,需要外部同步
10. 常见陷阱
- 直接访问不存在的键:会抛出异常,应用
get或getOrElse - 混淆可变和不可变操作:注意
+=和+的区别 - 期望保持顺序:普通Map不保证顺序,需要顺序用
ListMap或LinkedHashMap
最佳实践
- 优先使用不可变Map
- 使用
getOrElse进行安全访问 - 明确导入可变包名避免混淆
- 合理选择Map类型基于使用场景
这些关键点涵盖了Map的核心概念和日常使用中的重要注意事项。