map

一、map的定义

map是key-value数据结构,又称为字段或者关联数组。

map的声明:

var  map的变量名  map[keytype] valuetype

key的数据类型:golang中map的key可以是很多种类型,比如bool,数字,string,指针,channel,还可以是只包含前面几个类型的接口,结构体,数组。通常key为int、string

注意:slice,map还有function不可以,因为这几个没法用==来判断。

valuetype的类型:
valuetype的类型和key基本一样。通常为:数字(整数,浮点数),string,map,struct。

map声明的举例:
var a map[string]string
var a map[string]int
var a map[int]string
var a map[string]map[string]string
注意:声明是不会分配内存的,初始化需要make ,分配内存后才能赋值和使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
func main() {
    var a map[string]string
    a = make(map[string]string, 10)
 
    a["no1"] = "songjiang"
    a["no2"] = "wuyong"
    a["no3"] = "wusong"
    a["no1"] = "wuyong"
    fmt.Println(a)
}

map在使用前一定要make

map的key是不能重复,如果重复了,则以最后这个key-value为准
map的value是可以相同的.
map的key-value是无序
make内置函数数目

func make(Type, size IntegerType) Type
内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针。其具体结果取决于具体的类型:
切片:size指定了其长度。该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;
它必须不小于其长度,因此 make([]int, 0, 10) 会分配一个长度为0,容量为10的切片。
映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个小的起始大小。
通道:通道的缓存根据指定的缓存容量初始化。若 size为零或被省略,该信道即为无缓存的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main
 
import "fmt"
 
func main() {
    studentMap := make(map[string]map[string]string)
 
    studentMap["stu01"] = make(map[string]string, 3)
    studentMap["stu01"]["name"] = "tom"
    studentMap["stu01"]["sex"] = "男"
    studentMap["stu01"]["address"] = "北京长安街~"
 
    studentMap["stu02"] = make(map[string]string, 3)
    studentMap["stu02"]["name"] = "mary"
    studentMap["stu02"]["sex"] = "女"
    studentMap["stu02"]["address"] = "上海浦东"
 
    fmt.Println(studentMap)
    fmt.Println(studentMap["stu02"])
    fmt.Println(studentMap["stu01"]["address"])
}

 二、map的增删改查操作

1、map的增加和更新

如果key还没有就算增加,如果key已经存在就是修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(cities)
 
    cities["no3"] = "深圳~"
    fmt.Println(cities)
}

 2、map的删除

delete(map,"key") ,delete是一个内置函数,如果key存在,就删除该key-value,如果key不存在,不操作,但是也不会报错。

func delete(m map[Type]Type1, key Type)
内建函数delete按照指定的键将元素从映射中删除。若m为nil或无此元素,delete不进行操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(cities)
 
    cities["no3"] = "深圳~"
    fmt.Println(cities)
 
    delete(cities, "no1")
    fmt.Println(cities)
 
    delete(cities, "no5")
    fmt.Println(cities)
}

 如果我们要删除map的所有key ,没有一个专门的方法一次删除,可以遍历一下key, 逐个删除或者map = make(...),make一个新的,让原来的成为垃圾,被gc回收。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(cities)
 
    cities = make(map[string]string)
    fmt.Println(cities)
}

 3、map的查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(cities)
 
    val, ok := cities["no2"]
    if ok {
        fmt.Printf("键no2的值为%v\n", val)
    } else {
        fmt.Printf("没有键为no2")
    }
}

三、map的遍历

map的遍历使用for-range的结构遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(cities)
 
    for k, v := range cities {
        fmt.Printf("key = %v value = %v\n", k, v)
    }
 
    studentMap := make(map[string]map[string]string)
 
    studentMap["stu01"] = make(map[string]string, 3)
    studentMap["stu01"]["name"] = "tom"
    studentMap["stu01"]["sex"] = "男"
    studentMap["stu01"]["address"] = "北京长安街~"
 
    studentMap["stu02"] = make(map[string]string, 3)
    studentMap["stu02"]["name"] = "mary"
    studentMap["stu02"]["sex"] = "女"
    studentMap["stu02"]["address"] = "上海浦东"
 
    for k1, v1 := range studentMap {
        fmt.Printf("key1 = %v value2 = %v", k1, v1)
        for k2, v2 := range v1 {
            fmt.Printf("\t key2 = %v value2 = %v\n", k2, v2)
        }
        fmt.Println()
    }
 
}

四、map的长度

func len(v Type) int
内建函数len返回v的长度,这取决于具体类型:
数组:v中元素的数量
数组指针:*v中元素的数量(v为nil时panic)
切片、映射:v中元素的数量;若v为nil,len(v)即为零
字符串:v中字节的数量
通道:通道缓存中队列(未读取)元素的数量;若v为nil,len(v)即为零

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package main
 
import "fmt"
 
func main() {
    cities := make(map[string]string)
    cities["no1"] = "北京"
    cities["no2"] = "天津"
    cities["no3"] = "上海"
    fmt.Println(len(cities))
 
    studentMap := make(map[string]map[string]string)
 
    studentMap["stu01"] = make(map[string]string, 3)
    studentMap["stu01"]["name"] = "tom"
    studentMap["stu01"]["sex"] = "男"
    studentMap["stu01"]["address"] = "北京长安街~"
 
    studentMap["stu02"] = make(map[string]string, 3)
    studentMap["stu02"]["name"] = "mary"
    studentMap["stu02"]["sex"] = "女"
    studentMap["stu02"]["address"] = "上海浦东"
 
    fmt.Println(len(studentMap))
}

五、map切片

切片的数据类型如果是map,则我们称为slice of map,map切片,这样使用则map个数就可以动态变化了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main
 
import "fmt"
 
func main() {
    var monsters []map[string]string
    monsters = make([]map[string]string, 2)
 
    if monsters[0] == nil {
        monsters[0] = make(map[string]string, 2)
        monsters[0]["name"] = "牛魔王"
        monsters[0]["age"] = "500"
    }
 
    if monsters[1] == nil {
        monsters[1] = make(map[string]string, 2)
        monsters[1]["name"] = "玉兔精"
        monsters[1]["age"] = "300"
    }
 
    //if monsters[2] == nil {
    //  monsters[2] = make(map[string]string, 2)
    //  monsters[2]["name"] = "蜘蛛精"
    //  monsters[2]["age"] = "100"
    //}
 
    newMonster := map[string]string{
        "name": "新的妖怪",
        "age""200",
    }
 
    monsters = append(monsters, newMonster)
    fmt.Println(monsters)
}

六、map的排序

golang中没有一个专门的方法针对map的key进行排序
golang中的map默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样
golang中map的排序,是先将key进行排序,然后根据key值遍历输出即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
 
import (
    "fmt"
    "sort"
)
 
func main() {
    //map的排序
    m := make(map[int]int, 10)
    m[10] = 100
    m[1] = 13
    m[4] = 56
    m[8] = 90
 
    fmt.Println(m)
 
    //如果按照map的key的顺序进行排序输出,则先将map的key放入切片中,对切片进行排序,遍历切片,然后按照key来输出map的值
    var keys []int
    for k, _ := range m {
        keys = append(keys, k)
    }
 
    sort.Ints(keys)
    fmt.Println(keys)
 
    for _, k := range keys {
        fmt.Printf("m[%v] = %v\n", k, m[k])
    }
}

七、map使用的注意事项

1、map是引用类型,遵守引用类型传递的机制,在一个函数接收map,修改后,会直接修改原来的map

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
 
import "fmt"
 
func modify(m map[int]int) {
    m[50] = 100
}
 
func main() {
    m := make(map[int]int)
    m[1] = 90
    m[2] = 78
    m[10] = 1
    m[20] = 3
    fmt.Println("map修改前", m)
    modify(m)
    fmt.Println("map修改后", m)
}

2、map的容量达到后,再想map增加元素,会自动扩容,并不会发生panic,也就是说map能动态的增长键值对(key-value)

3、map的value也经常使用struct类型,更适合管理复杂的数据(比value是一个map更好)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package main
 
import "fmt"
 
func modifyUser(users map[string]map[string]string, name string) {
    if users[name] != nil {
        users[name]["pwd"] = "888888"
    } else {
        users[name] = make(map[string]string, 2)
        users[name]["pwd"] = "888888"
        users[name]["nickname"] = "这是我的昵称:" + name
    }
}
 
func main() {
    //使用 map[string]map[string]sting 的map类型
    //key: 表示用户名,是唯一的,不可以重复
    //如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息,(包括昵称nickname 和 密码 pwd)。
    //编写一个函数modifyUser(users map[string]map[string]sting, name string)完成上述功能
    users := make(map[string]map[string]string, 10)
    users["smith"] = make(map[string]string, 2)
    users["smith"]["pwd"] = "999999"
    users["smith"]["nickname"] = "小狗"
 
    modifyUser(users, "tom")
    modifyUser(users, "mary")
    modifyUser(users, "smith")
 
    fmt.Println(users)
}

 

posted on   lina2014  阅读(607)  评论(0编辑  收藏  举报

导航

< 2025年2月 >
26 27 28 29 30 31 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 1
2 3 4 5 6 7 8
点击右上角即可分享
微信分享提示