Go Map
Go中内置类型,其使用hash表实现,为引用类型。
无序键值对集合,通过key(类似索引)快速检索数据。
Map是什么
Map是一种数据结构,是一个集合,用于存储一系列无序的键值对。
基于键存储的,可以快速快速检索数据,键指向与该键关联的值
Map内部实现
Map存储的是什么?Map存储的是无序的键值对集合。
Map基于什么?基于散列表(hash表),故每次迭代Map,打印的key和value是无序的,每次迭代不一样。
Map散列表特点是?包含一组桶,每次存储和查找键值对的时候,都要先选择一个桶。
如何选择桶?把指定的键传给散列函数,就可索引到相应的桶,进而找到对应的键值。
这种方式的好处是?存储的数据越多,索引分布越均匀,所以我们访问键值对的速度也就越快
Map声明和初始化
Map的创建方式?两种方法:make函数,map字面量。
法一:make函数
m:=make(map[string]int) m["张三"] = 21
法二:map字面量创建和初始化
m:= map[string]int{"张三":21} m2:= map[string]int{"张三":21,"李四":22}
m3:= map[string]int{} //空map
如何创建一个nil的map? var m4 map[string]int 这样我们是不能操作存储键值对的,必须要初始化后才可以
var m4 map[string]int m4 = make(map[string]int) m4["张三"] = 21 fmt.Println(m4) // map[张三:21]
Map的键可以是?
除了slice,map,function的内建类型都可以作为key
Struct不包含上述字段,可以作为key
任何值:内置的类型、结构类型。原则是:可以使用 == 进行比较。
故切片、函数以及含有切片的结构类型就不能用于Map的键,因为其具有引用语义,不可比较。
使用Map
Map通过键来使用,类似数组切片通过索引。
delete(map, key) 函数用于删除集合的元素, 参数为 map 和其对应的 key。删除函数不返回任何值。
注:
make 用于内建类型(map、slice 和channel)的内存分配
内建函数make(T, args),make只能创建slice、map和channel,并且返回一个有初 始值(非零)的T类型,而不是*T
new 用于各种类型的内存分配
内建函数new(T)与其他语言相同:分配了零值填充的T类型的内存空间,它返回了一个指针*T,指向新分配
m:= make(map[string]int) m["张三"] = 21 //获取一个Map键的值 age := m["张三"] fmt.Println("张三的年龄",age) //如果张三存在 对值修改 注:Map提供了一个检测键值对是否存在的方法 age1,exists := m["李四"] if(exists){ fmt.Println("李四的年龄",age1) }else { fmt.Println("没有李四") } //删除一个Map的键值对用delete 注:delete可以删除不存在的键,只是没有任何作用 delete(m,"张三") fmt.Println(m)
输出:
张三的年龄 21 没有李四 map[]
如何遍历Map?for range
使用range遍历key,或者遍历key,value对
不保证遍历顺序,如需顺序,需手动对key排序
使用 len(map) 获得元素个数
func main() { m := map[string]int{"张三": 21} for key, value := range m { fmt.Println(key, value) } sortOrder() } func sortOrder(){ m1 := map[string]int{"张三": 22,"王五": 60, "李六": 33} var names []string for name := range m1 { names = append(names, name) } sort.Strings(names) //排序 for _, key := range names { fmt.Println(key, m1[key]) } }
输出:
张三 21 张三 22 李六 33 王五 60
在函数间传递Map
传递的不是一个Map副本。
func main() { m2 := map[string]int{"王五": 60, "张三": 21} modify(m2) fmt.Println(m2["张三"]) //10 } func modify(dict map[string]int) { dict["张三"] = 10 }