定义
map:一个无序的key-value对的集合,其中所有的key的值不同,通过给定的key对其进行检索、更新或删除可以在 O(1) 的时间复杂度内完成。
map[KeyType]ValueType
其中 KeyType表示键的类型 ValueType表示键对应值的类型
基本使用
初始化
make(map[KeyType]ValueType, [cap])
其中 cap表示map的容量,该参数虽然不是必须的,但是我们应该在初始化map的时候就为其指定一个合适的容量。
ages := make(map[string]int)
map字面值的语法创建map,同时指定一些初始值
ages := map[string]int{
"alice": 31,
"tom": 34,
}
相当于
ages := make(map[string]int)
ages["alice"] = 31
ages["tom"] = 34
元素的访问 key中的value
ages["jack"] = 32
fmt.Println(ages["jack"]) // "32"
删除元素
格式:delete(map, key)
delete(ages, "alice") // remove element ages["alice"]
遍历
可以用for-range进行遍历
for name, age := range ages {
fmt.Printf("%s\t%d\n", name, age)
}
注意:遍历的顺序是随机的
这是故意的,每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。----《Go语言圣经》
按指定顺序遍历
如果要按顺序遍历key/value对,我们必须显式地对key进行排序,可以使用sort包的Strings函数对字符串slice进行排序。
import "sort"
var names []string
for name := range ages {
names = append(names, name)
}
sort.Strings(names)
for _, name := range names {
fmt.Printf("%s\t%d\n", name, ages[name])
}
其他例子:
func main() {
rand.Seed(time.Now().UnixNano()) //初始化随机数种子
var scoreMap = make(map[string]int, 200)
for i := 0; i < 100; i++ {
key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
value := rand.Intn(100) //生成0~99的随机整数
scoreMap[key] = value
}
//取出map中的所有key存入切片keys
var keys = make([]string, 0, 200)
for key := range scoreMap {
keys = append(keys, key)
}
//对切片进行排序
sort.Strings(keys)
//按照排序后的key遍历map
for _, key := range keys {
fmt.Println(key, scoreMap[key])
}
}
判断某个值是否存在
if age, ok := ages["bob"]{
fmt.Println(age)
}else{
fmt.Println("查无此人")
}
元素为map类型的切片
func main() {
var mapSlice = make([]map[string]string, 3)
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
// index:0 value:map[]
// index:1 value:map[]
// index:2 value:map[]
}
fmt.Println("after init")
// 对切片中的map元素进行初始化
mapSlice[0] = make(map[string]string, 10)
mapSlice[0]["name"] = "小羊爱吃肉"
mapSlice[0]["password"] = "123456"
mapSlice[0]["address"] = "湖北"
for index, value := range mapSlice {
fmt.Printf("index:%d value:%v\n", index, value)
// index:0 value:map[address:湖北 name:小羊爱吃肉 password:123456]
// index:1 value:map[]
// index:2 value:map[]
}
}
值为切片类型的map
func main() {
var sliceMap = make(map[string][]string, 3)
fmt.Println(sliceMap)
// map[]
fmt.Println("after init")
key := "中国"
value, ok := sliceMap[key]
if !ok {
value = make([]string, 0, 2)
}
value = append(value, "北京", "上海")
sliceMap[key] = value
fmt.Println(sliceMap)
// map[中国:[北京 上海]]
}
案例
判断两个map是否包含相同的key和value
和slice一样,map之间也不能进行相等比较;唯一的例外是和nil进行比较。要判断两个map是否包含相同的key和value,我们必须通过一个循环实现:
func equal(x, y map[string]int) bool {
if len(x) != len(y) {
return false
}
for k, xv := range x {
if yv, ok := y[k]; !ok || yv != xv {
return false
}
}
return true
}
func main(){
if equal(map[string]int{"A": 0}, map[string]int{"B": 42}) {
println("true")
} else {
println("false")
}
}
以上案例来自于《Go语言圣经》
寻找最长不含重复字符的子串
// abcabcbb找出abc bbbbb找出b pwwkew找出wke
package main
import "fmt"
func length0fnonrepeatingsubstr(s string) int {
last0ccurred := make(map[byte]int)
start := 0
maxlength := 0
for i, ch := range []byte(s) {
if lastI, ok := last0ccurred[ch]; ok && lastI >= start {
start = lastI + 1
}
if i-start+1 > maxlength {
maxlength = i - start + 1
}
last0ccurred[ch] = i
}
return maxlength
}
func main() {
fmt.Println(
length0fnonrepeatingsubstr("abcabcbb"))
fmt.Println(
length0fnonrepeatingsubstr("bbbbb"))
fmt.Println(
length0fnonrepeatingsubstr("pwwkew"))
fmt.Println(
length0fnonrepeatingsubstr(""))
fmt.Println(
length0fnonrepeatingsubstr("abcdef"))
}