go语言基础—map

1、map的概念


哈希表

1、哈希表是一种巧妙且实用的数据结构。

2、它是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value。


map

1、在go中,一个map就是一个哈希表的引用

2、map的类型写作map[K]YK是key的数据类型,Y是value的数据类型,KY可以是不相同的

3、所有的key必须是声明的同一类型,并且必须是支持==比较运算符的,这是为了保证key的独立性

4、所有的value必须是声明的同一类型,没有其他限制


2、map的创建

make函数

// 使用make函数创建的map是一个空map,但不是一个值为nil的map
// 可以继续对它进行存取值等一切正常的map操作
ages := make(map[string]int)

字面量

// 使用字面量的方式,有简短语法:= 和关键字语法var
// map是一个对哈希表的引用,因此当不引用任何哈希表,包括空的哈希表时,map值为nil,即map的零值
// map为nil时,无法进行存取值,因为找不到引用的哈希表

ages := map[string]int  // 声明一个map,但是没有初始化,即nil

names := map[string]int{}  // 声明一个map,并初始化为空

3、常用方法

3.1 存取值

//  通过[]按key存取值,类似于python的字典
//  通过内置方法delete方法删除值,先访问目标值,再删除
//  访问map值时,若不存在该key,则返回map的零值

func main() {
	ages := make(map[string]int)
	ages["egon"] = 18  // 添加值到map
	ages["nick"] = 19
	fmt.Println(ages)  
	fmt.Println(ages["egon"])  // 从map中取值
    
    delete(ages,"egon")  // 删除map中的值
    fmt.Println(ages)
	fmt.Println(ages["egon"])  // egon不存在,结果为零值
}

3.2 遍历map


禁止对map元素取址操作

1、map中的元素并不是变量

2、map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效

_ = &ages["bob"] // compile error: cannot take address of map element

for...range循环遍历

1、使用range风格的for循环,可以遍历map的所有key/value对

2、map是一个对哈希表的引用,而哈希表是一个无序的key/value对的集合,因此map的迭代顺序也是不确定的

3、不同的哈希函数实现也可能导致不同的遍历顺序

4、实际中,对map的遍历时随机的

for name, age := range ages {
    fmt.Printf("%s\t%d\n", name, age)
}

5、若要有序遍历,那么需要先将key排序,通过有序的key,可以有序的遍历map,在go中,可以通过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])
}

3.3 解决默认零值的冲突

1、当访问的map元素不存在时,默认返回零值

2、因此,无法判断到底是不存在返回的零值还是真正的值为零值的元素

解决办法:

// map[K]的方式访问map元素时,有两个返回值,第一个时value,第二个是布尔值,布尔值变量一般命名为ok

age, ok := ages["bob"]
if !ok { /* "bob" is not a key in this map; age == 0. */ }

// 一般用下面的方式连用
if age, ok := ages["bob"]; !ok { /* ... */ }

3.4 比较

map之间也不能进行相等比较,唯一的例外是和nil进行比较,判断两个map是否包含相同的key和value,必须通过一个循环实现,再map长度相同的情况下,逐个比较每个元素

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
}

4、实现set类型的功能

go中没有set类型,但是map中的key是不相同的,可以用map实现类似set的功能

posted @ 2019-12-26 21:49  W文敏W  阅读(164)  评论(0)    收藏  举报