1、基本介绍
map是key-value数据结构,又称为字段或者关联数组。类似其它编程语言的集合,
在编程中是经常使用到。
2、map和数组的区别
map相对数组而言,可以存储信
var map变量名 map[keytype]valuetype
1、 key 可以是什么类型
golang中的map,的 key 可以是很多种类型,比如 bool, 数字,string, 指针, channel , 还可以是只包含前面几个类型的 接口, 结构体, 数组
通常为int 、string
注意: slice, map 还有 function 不可以,因为这几个没法用 == 来判断
2、 valuetype 可以是什么类型
valuetype的类型和key基本一样,这里我就不再赘述了
通常为: 数字(整数,浮点数),string,map,struct
3、 注意和说明几点
4、示例代码
package main
import (
"fmt"
)
func main() {
var map1 map[string]map[string]string
//在map1中保存2个学生信息[编号唯一, (名字,爱好,年龄)]
//1. 先给map1 make空间
map1 = make(map[string]map[string]string, 3)
//2. 给map1["no1"] make空间
map1["no1"] = make(map[string]string, 3)
map1["no1"]["name"] = "小明"
map1["no1"]["hobby"] = "看世界杯"
map1["no1"]["age"] = "20"
//3. 给map1["no2"] make空间
map1["no2"] = make(map[string]string)
map1["no2"]["name"] = "小李~"
map1["no2"]["hobby"] = "看欧洲杯"
map1["no2"]["age"] = "30"
//3. 给map1["no2"] make空间
map1["no2"] = make(map[string]string)
map1["no2"]["name"] = "小张"
map1["no2"]["hobby"] = "看欧洲杯~"
map1["no2"]["age"] = "40"
fmt.Println("map1=",map1)
}
package main
import (
"fmt"
)
func main() {
//几个map的小案例
//map1 map[int]string
//1. map1 就是这个map类型的名字
//2. map 是一个关键字表示是一个map,固定的
//3. [int] 表示这个map的key的数据类型
//4. string 表示这个map的value的数据类型
var map1 map[int]string
//在使用map之前,需要先make一个数据空间
// make(map[int]string, 10)
//1. make是个函数,表示给map1分配数据空间
//2. map[int]string 分配的空间类型
//3. 10 表示分配空间大小
map1 = make(map[int]string, 10)
map1[10] = "tom"
map1[11] = "tom"
fmt.Println(map1)
//key还可以是 接口,结构体,数组
var arr1 = [3]int{1,2,3}
var arr2 = [3]int{1,2,4}
fmt.Println("arr1=arr2?", arr1==arr2)
var map2 map[[3]int]string
map2 = make(map[[3]int]string , 10)
map2[arr1] = "jack"
map2[arr2] = "scott"
fmt.Println("map2", map2)
}
1、先声明再make
var m map[string]string
m = make(map[string]string,10)
2、声明的同时make
var m = make(map[string]string,10)
3、声明并直接赋值
var m map[string]string map[string]string{"id":"01"}
1、map增加和更新:
map["key"] = value
//如果key还没有,就是增加,如果key存在就是修改。
var heros = map[string]string{
"no1" : "宋江",
"no2" : "小卢",
"no3" : "吴用",
} // 底层隐藏 make
heros["no4"] = "公孙胜" //新增
heros["no1"] = "武松" //覆盖
fmt.Println("herso", heros)
//删除map的一个key-val
delete(heros, "no2")
fmt.Println("herso", heros)
//清空map
//heros = make(map[string]string)
fmt.Println("herso", heros)
2、map删除:
1)delete(map,"key") ,
delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作,但是也不会报错
2)细节说明
代码示例:
//删除map的一个key-val
delete(heros, "no2")
fmt.Println("herso", heros)
//清空map
//heros = make(map[string]string)
fmt.Println("herso", heros)
3、map查找
//从map中,查找对应的key-val
//如果有 res = true
//如果没有 res = false
val, res := heros["no1"]
if res {
fmt.Printf("有no1 对应的值=%v\n", val)
} else {
fmt.Printf("没有\n")
}
4、map增删改查完整代码:
package main
import (
"fmt"
)
func main() {
var heros = map[string]string{
"no1" : "宋江",
"no2" : "小卢",
"no3" : "吴用",
} // 底层隐藏 make
heros["no4"] = "公孙胜" //新增
heros["no1"] = "武松" //覆盖
fmt.Println("herso", heros)
//删除map的一个key-val
delete(heros, "no2")
fmt.Println("herso", heros)
//清空map
//heros = make(map[string]string)
fmt.Println("herso", heros)
//从map中,查找对应的key-val
//如果有 res = true
//如果没有 res = false
val, res := heros["no1"]
if res {
fmt.Printf("有no1 对应的值=%v\n", val)
} else {
fmt.Printf("没有\n")
}
}
map的遍历使用for-range的结构遍历
package main
import (
"fmt"
)
func main() {
var map1 map[string]map[string]string
//在map1中保存2个学生信息[编号唯一, (名字,爱好,年龄)]
//1. 先给map1 make空间
map1 = make(map[string]map[string]string, 3)
//2. 给map1["no1"] make空间
map1["no1"] = make(map[string]string, 3)
map1["no1"]["name"] = "小明"
map1["no1"]["hobby"] = "看世界杯"
map1["no1"]["age"] = "20"
//3. 给map1["no2"] make空间
map1["no2"] = make(map[string]string)
map1["no2"]["name"] = "小李~"
map1["no2"]["hobby"] = "看欧洲杯"
map1["no2"]["age"] = "30"
//3. 给map1["no2"] make空间
map1["no3"] = make(map[string]string)
map1["no3"]["name"] = "梅西"
map1["no3"]["hobby"] = "踢足球"
map1["no3"]["age"] = "32"
//fmt.Println("map1=",map1)
//遍历 for -- range
for key1, val1 := range map1 {
fmt.Printf("编号为%v\n", key1)
//对val1 (map) 再次遍历
for key2, val2 := range val1 {
fmt.Printf("\t%v=%v\n", key2, val2)
}
fmt.Println()
}
}
1、基本介绍
切片的数据类型如果是map,则我们称为 slice of map,map切片,这样使用则map个数就可以动态变化了。
2、案列
要求:使用一个map来记录monster的信息 name 和 age, 也就是说一个monster对应一个map,并且妖怪的个数可以动态的增加=>map切片
package main
import (
"fmt"
)
func main() {
//演示map使用
// 要求:使用一个map来记录monster
// 的信息 name 和 age, 也就是说一个
// monster对应一个map,并且妖怪的个
// 数可以动态的增加=>map切片
//1. 声明一个map切片
var monsters []map[string]string
//2. 我们先给 切片 分配空间
monsters = make([]map[string]string, 3)
//3. 给第一个妖怪的map分配空间
if monsters[0] == nil {
monsters[0] = make(map[string]string, 2) // monster 记录什么
monsters[0]["name"] = "红孩儿"
monsters[0]["age"] = "10"
}
//3. 给第2个妖怪的map分配空间
if monsters[1] == nil {
monsters[1] = make(map[string]string, 2) // monster 记录什么
monsters[1]["name"] = "牛魔王"
monsters[1]["age"] = "500"
}
//3. 给第2个妖怪的map分配空间
if monsters[2] == nil {
//monsters[2] = make(map[string]string, 2) // monster 记录什么
monsters[2]["name"] = "白骨精"
monsters[2]["age"] = "400"
}
fmt.Println("monsters=", monsters)
}
1、基本介绍
golang中没有一个专门的方法针对map的key进行排序
golang中的map默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样.
golang中map的排序,是先将key进行排序,然后根据key值遍历输出即可
2、案例演示
package main
import (
"fmt"
)
func test(m map[string]string) {
m["no1"] = "tomjack"
}
//先定义一个结构体(struct Stu)
type Stu struct {
Name string
Age int
IsMarrid bool
}
func main() {
var heros2 = map[string]string{
"no1" : "宋江",
"no2" : "小卢",
"no3" : "吴用",
"no4" : "豹子头",
"no5" : "武松",
"no6" : "鲁智深",
}
heros2["no7"] = "顺平" //只要有一次make, 后面添加key-val就会自动增长
fmt.Println("heros2=", heros2)
test(heros2)
fmt.Println("heros2=", heros2)
// map的value 也经常使用struct 类型,
// 更适合管理复杂的数据(比前面value是一个map更好),
// 比如value为 Student结构体
// 【案例演示,因为还没有学结构体,体验一下即可】
//需求:使用map保存2个学生 【学号[唯一], 学生信息[名字,年龄(int), 婚否(bool)]】
//1. 先定义一个结构体(struct Stu)
//2. 创建map
//
var stusMap map[string]Stu
//3. 给stusMap make空间
stusMap = make(map[string]Stu, 2)
//4. 给stusMap放入学生
stu1 := Stu{"贾宝玉", 18, false}
stu2 := Stu{"林黛玉", 16, false}
stusMap["no001"] = stu1
stusMap["no002"] = stu2
fmt.Println("stusMap=",stusMap)
}
package main
import (
"fmt"
"sort"
)
//封装一个冒泡
func bubbleSort(keysSlice []string) {
var temp string
//对冒泡做一个优化, 思路如果在内层循环中,一次交换交换都没有发生过,则说明
//该数组已经是一个有序数列,就不需要再比较.
var flag = false //
//将for 做成双层循环
for j := 0; j < len(keysSlice) - 1; j++ {
for i := 0; i < len(keysSlice) - 1 - j; i++ {
//如果前面的数比后面的数大,就交换
if keysSlice[i] < keysSlice[i + 1] {
flag = true
temp = keysSlice[i]
keysSlice[i] = keysSlice[i + 1]
keysSlice[i + 1] = temp
}
}
if flag == true { //交换过
flag = false
} else {
// 一次都没有交换过
break
}
}
}
func main() {
var heros = map[int]string{
1 : "宋江",
2 : "小卢",
3 : "吴用",
4 : "豹子头",
5 : "关胜",
6 : "秦明",
7 : "武松",
} // 底层隐藏 make
//遍历
for key, val := range heros {
fmt.Printf("key=%v val=%v\n", key, val)
}
//现在我们有这样一个需求,按照key的string排序.
//如果我们的map的key是整数,那么比较简单. sort.Ints()
//1. 先将heros的所有key放入到一个切片中 []int
var keysSlice []int
for key, _ := range heros {
keysSlice = append(keysSlice, key)
}
//2. 使用系统提供方法sort.Ints()排序
sort.Ints(keysSlice) //切片是引用类型
fmt.Println("keysSlice=", keysSlice)
fmt.Println()
for _, val := range keysSlice {
fmt.Printf("key=%v val=%v\n", val, heros[val])
}
//3. 我如果希望从大到小显示==》
//4.
fmt.Println("---------------------------------")
fmt.Println("---------------------------------")
fmt.Println("---------------------------------")
fmt.Println("---------------------------------")
//map
var heros2 = map[string]string{
"no1" : "宋江",
"no2" : "小卢",
"no3" : "吴用",
"no4" : "豹子头",
"no5" : "武松",
"no6" : "鲁智深",
} // 底层隐藏 make
//按照 key 的字符串大小排, 从小到大...
// heros2==> map 的 key==> keySlice2 ==排序【从小到大】==> 遍历keySlice2,显示数据.
var keysSlice2 []string
for key, _ := range heros2 {
keysSlice2 = append(keysSlice2, key)
}
//keySlice2 ==排序【从小到大】冒泡
bubbleSort(keysSlice2)
//遍历keySlice2,显示数据
for _, val := range keysSlice2 {
fmt.Printf("key=%v val=%v\n", val, heros2[val])
}
//补充一个知识点, 字符串本身是可以比较大小 ??
//fmt.Println("no3>no2=", "no3" > "no2")
}
1、map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map
2、 map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说map 能动态的增长 键值对(key-value) 【案例演示】
var heros2 = map[string]string{
"no1" : "宋江",
"no2" : "小卢",
"no3" : "吴用",
"no4" : "豹子头",
"no5" : "武松",
"no6" : "鲁智深",
}
heros2["no7"] = "顺平" //只要有一次make, 后面添加key-val就会自动增长
fmt.Println("heros2=", heros2)
test(heros2)
fmt.Println("heros2=", heros2)
3、map的value 也经常使用struct 类型,更适合管理复杂的数据(比前面value是一个map更好),比如value为 Student结构体 【案例演示】
var onlineUsers map[int]*bean.User = make(map[int]*bean.User)
4、如何计算Map的长度