介绍
所谓的映射表其实就是: 键值对, 在不同的编程语言中有不同的叫法:
- Python 中叫做: 字典
dict - JavaScript 中叫做: 对象
object - Lua 中叫做: 元表
table - Java 中叫做: 哈希表
HashMap
go
package main
import "fmt"
func main() {
// 定义一个映射表:
// 变量名 := map[key-type]value-type {}
scores := map[string]int {
// key: value 合起来叫做: 键值对/字段
// key: 叫做: 键, 键名, 属性名, 字段名
// value: 叫做: 值, 键值, 属性值, 字段值
"zhangsan": 78,
"lisi": 88,
}
fmt.Println(scores)
}初始化
go
package main
import "fmt"
func main() {
// 1.声明时不赋值
m1 := map[string]int{}
m1["a"] = 1
m1["b"] = 2
m1["c"] = 3
fmt.Println("m1:", m1)
// 2.声明时直接赋值
m2 := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
fmt.Println("m2:", m2)
// 2.使用 make 函数创建映射表
m3 := make(map[string]int)
m3["a"] = 1
m3["b"] = 2
m3["c"] = 3
fmt.Println("m3:", m3)
}map 数据的特点
- map 是一种非线性列表(或者叫: 无序列表)集合
- map 存储的是 key-value 键值对
- map 中的 key 具有唯一性
- map 中的 key 可以是任意可比较相等的数据类型: int/float/bool/string 等
- map 中的 value 可以是任意类型
go
package main
import "fmt"
func main() {
// key 可以是 string
mp1 := map[string]string{
"a": "1",
"b": "2",
}
fmt.Println(mp1)
// key 可以是 int/bool/float 等等
// 但是用的最多的还是 string
mp2 := map[int]int{
1: 11,
2: 22,
}
fmt.Println(mp2)
// 值可以是 切片
mp3 := map[string][]int{
"startPos": {0, 0},
"endPos": {5, 5},
}
fmt.Println(mp3)
// 值可以是 map
mp4 := map[string]map[string]int{
"startPos": {
"x": 0,
"y": 0,
},
"endPos": {
"x": 100,
"y": 100,
},
}
fmt.Println(mp4)
}不能做为 key 的数据类型
由于映射表中不能有两个相同的 key, 否则会覆盖, 所以:只有可以比较的数据类型 才能作为 key, 不能比较的数据类型就无法作为映射表的 key, 不能比较是否相等的数据类型有:
- 函数
- 数组
- 切片
- map
go
package main
import "fmt"
func main() {
s1 := []int{1}
s2 := []int{1}
// invalid operation: s1 == s2 (slice can only be compared to nil)
// fmt.Println(s1 == s2)
// invalid map key type []int
m := map[[]int]int{
s1: 1,
s2: 2,
}
fmt.Println(m)
}操作 map
go
package main
import "fmt"
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
// 获取字段的个数
fmt.Println("获取字段的个数:", len(m)) // 3
// 获取字段
fmt.Println("工具key获取对应字段的值:", m["a"]) // 1
// 枚举所有字段, for range 枚举的顺序是随机的
for k, v := range m {
fmt.Printf("遍历字段 k=%v, v=%v \n", k, v)
}
// 增加字段
m["d"] = 4
fmt.Println("增加字段后:", m) // map[a:1 b:2 c:3 d:4]
// 修改字段
m["a"] = 11
fmt.Println("修改字段后:", m) // map[a:11 b:2 c:3 d:4]
// 删除字段
delete(m, "b")
fmt.Println("删除字段后:", m) // map[a:11 c:3 d:4]
}访问字段 & 访问不存在的字段
在 go 语言中, 并不像 JS 那样会 隐式类型转换, 在判断的时候, 必须要是 bool 值
go
package main
func main() {
m := map[string]int{
"test": 1,
}
// 反面案例: 这样肯定是不行的,
// 这个 m["test"] 表达式结果不是布尔值
// if m["test"] {
// }
// 这样是可以的, 因为这个表达式的结果是布尔值
if m["test"] == 1 {
}
}go
package main
import "fmt"
func main() {
m := map[string]int{
"a": 1,
"b": 2,
"c": 3,
}
// 值, 是否是否存在的布尔值
// 如果字段不存在, 默认的值是 0(类型的默认值)
c, cExist := m["c"]
d, dExist := m["d"]
// 语法糖: 可以写成这样:
// if c, exist := m["c"]; exist {
// fmt.Println("c:", c, exist) // c: 3 true
// }
fmt.Println("c:", c, cExist) // c: 3 true
fmt.Println("d:", d, dExist) // d: 0 false
}map 中存储不同类型的值
在描述一个物体的信息, 可能需要多个类型的值, 比如一个人的名字应该是 字符串, 身高体重应该是 int/float 可以计算的数据类型
go
package main
import "fmt"
func main() {
// any 类型表示: 不限制类型/可以是任何类型
user := map[string]any{
"name": "张三",
"age": 18,
"isMale": true,
}
fmt.Println(user)
}