人生苦短我使用GO——Map

目录

引入

Map的实现

Map的基本使用

查找和判断某个值是否存在

                判断某个值是否存在

遍历Map

元素删除

        按照指定顺序遍历Map

                元素为map类型的切片

        值为切片类型的map

将Map传递到函数


引入

复合类型 值的类型 值的数量 值的索引

数组  相同  固定  下标

切片  相同  动态  下标

结构体 不相同 固定  属性名

Map 相同 动态  key键

map(key:value)    k:v
​
key:除了切片等引用类型,其他类型即可
​
value:可以是所有类型的值

Map是一种数据结构,用于存储一系列无序的键值对,Map基于键来存储值。

Map功能强大的地方是,能够基于键快速检索数据。键就像索引一样,指向与该键关联的值。

与C++、Java不一样,Go使用Map不需要引入任何库。

Map的实现

因为映射也是一个数据集合,所以也可以使用类似处理数组和切片的方式来迭代映射中的元素。但映射是无序集合,所以即使以同样的顺序保存键值对,每次迭代映射时,元素顺序也可能不一样。无序的原因是映射的本质使用了散列表。

map在底层是用哈希(hash)表实现的,在C:\Program Files\Go\src\hash\maphash\maphash.go,map是一个hash数组列表,由一个个bucket组成,示意图如下:

 

        每一个元素都被称为bucket的结构体,每一个bucket可以保存8个键值对,所有元素被hash算法填入到数组的bucket中,bucket填满后,将通过一个overflow指针来扩展一个bucket从来形成链表,以此来解决hash冲突的问题,map就是一个bucket指针型的一维数组。

创建map语法如下:

//创建一个映射,键的类型string,值的类型int
dict : mmake(map[ string]int)
//创建一个映射,键值类型都是string,并对两个键值对进行初始化
dict:=map[string]stringi""name" : "zhangsan" , "address" : "nanjing"}

映射的键可以是任何值,这个值的类型并不限制,内置类型或者结构体都可以,需要确定这个值可以使用==运算符做比较需要注意的是,切片、函数以及包含切片的结构类型由于是引用类型,均不能作为映射的键

dict : =map[[]string]int
//报错: incomparable map key type []string
​
//切片作为值,不可以作为键
dict:=map[int][ ]string

Map的基本使用

map中的数据都是成对出现的

package main

import "fmt"

func main() {
	var soMap = make(map[string]int, 8)
	soMap["老王"] = 45
	soMap["隔壁"] = 7

	fmt.Println(soMap)
	fmt.Println(soMap["隔壁"])
	fmt.Printf("类型是:%T", soMap)
}


运行结果
map[老王:45 隔壁:7]
7
类型是:map[string]int

还可以在声明时候添加map

package main

import "fmt"

func main() {

	var Cmap = map[string]string{

		"xiaoming": "mingxiao",
		"zhangsan": "sanzhang",
	}

	fmt.Println(Cmap)
}

运行结果
map[xiaoming:mingxiao zhangsan:sanzhang]

查找和判断某个值是否存在

从Map取值时有两种方式。

第一种方式是,获得值以及一个表达这个值是否存在的标志。

package main

import "fmt"

func main() {

	var soMap = make(map[string]int, 8)
	soMap["老王"] = 45
	soMap["隔壁"] = 7
	key, value := soMap["老王"]
	fmt.Println(key, value)

}

运行结果
45 true

        第二种方式是,只返回键对应的值,再判断这个值是否有零值,以此来确定键是否存在。这种方式 只能用在映射存储的值都是非零值的情况。  

package main

import "fmt"

func main() {
	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"

	value := soMap["老王"]
	if value != " " {
		fmt.Println(value)
	}

}

运行结果
45

                判断某个值是否存在

package main

import "fmt"

func main() {

	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"

	value, ok := soMap["隔壁"]
	if ok {
		fmt.Println(value)
	} else {
		fmt.Println("没有这个人")
	}
}


运行结果
7

package main

import "fmt"

func main() {

	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"

	value, ok := soMap["老李"]
	if ok {
		fmt.Println(value)
	} else {
		fmt.Println("没有这个人")
	}
}

运行结果
没有这个人

遍历Map

        使用rang迭代Map里面所有值

package main

import "fmt"

func main() {

	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"

	for key, value := range soMap {
		fmt.Println(key, value)
	}

}

运行结果
老王 45
隔壁 7

        但我们只想遍历key的时候,可以这样写

package main

import "fmt"

func main() {
	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"

	for key := range soMap {
		fmt.Println(key)
	}


/*或者也可以
    for key,_:= range soMap {
		fmt.Println(key)
	}*/
}

运行结果
老王
隔壁

注意:遍历map时的元素顺序与添加键值对的顺序无关。

元素删除

内置函数delete()用于蒯除容器内的元素,

delete()函数的格式如下:

    delete(map, key)

其中,

    map:表示要删除键值对的map

    key:表示要删除的键值对的键

从map中删除键为key的键值对。如果key这个键不存在,那么这个调用将什么都不发生,也不会有任何副作用。但是如果传入的map变量的值是nil,该调用将导致程序抛出异常(panic). 

package main

import "fmt"

func main() {

	var soMap = make(map[string]string, 8)
	soMap["老王"] = "45"
	soMap["隔壁"] = "7"
	soMap["张三"] = "10086"
	soMap["李四"] = "10010"

	for key, value := range soMap {
		fmt.Println(key, value)
	}
	delete(soMap, "隔壁")

	fmt.Println("------------------删除之后----------------")

	for key, value := range soMap {
		fmt.Println(key, value)
	}
}

运行结果

老王 45
隔壁 7
张三 10086
李四 10010
------------------删除之后----------------
老王 45
张三 10086
李四 10010

        按照指定顺序遍历Map

package main

import (
	"fmt"
	"math/rand"
	"sort"
	"time"
)

func main() {
	rand.Seed(time.Now().UnixNano()) //随机数

	var doMap = make(map[string]int, 100)
	for i := 0; i < 10; i++ {
		name := fmt.Sprintf("ns%d", i) //生成ns开头的数字
		age := rand.Intn(50)           //随机生成0-50的数字作为年龄
		doMap[name] = age
	}

	//取出map的值放入到切片中
	var key = make([]string, 0, 100)
	for name := range doMap {
		key = append(key, name)
	}

	//对切片进行排序
	sort.Strings(key)
	//排完序进行遍历

	for _, name := range key {

		fmt.Println(name, doMap[name])
	}
}

运行结果

ns0 18
ns1 27
ns2 19
ns3 46
ns4 2
ns5 44
ns6 1
ns7 11
ns8 30
ns9 34

                元素为map类型的切片

package main

import "fmt"

func main() {
	var mapSlice = make([]map[string]string, 3)
	for index, value := range mapSlice {
		fmt.Printf("index:%d value:%v\n", index, value)
	}
	fmt.Println("----------------初始化之后---------------------")
	// 对切片中的map元素进行初始化
	mapSlice[0] = make(map[string]string, 10)
	mapSlice[0]["name"] = "晓彬"
	mapSlice[0]["password"] = "123456"
	mapSlice[0]["address"] = "北京东路"

	mapSlice[1] = make(map[string]string, 10)
	mapSlice[1]["name"] = "小红"
	mapSlice[1]["password"] = "123456"
	mapSlice[1]["address"] = "南京路"
	mapSlice[2] = make(map[string]string, 10)
	mapSlice[2]["name"] = "小王"
	mapSlice[2]["password"] = "123456"
	mapSlice[2]["address"] = "南京西路"
	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[]
----------------初始化之后---------------------
index:0 value:map[address:北京东路 name:晓彬 password:123456]
index:1 value:map[address:南京路 name:小红 password:123456]
index:2 value:map[address:南京西路 name:小王 password:123456]

        值为切片类型的map

package main

import "fmt"

func main() {
	var sliceMap = make(map[string][]string, 3)
	fmt.Println(sliceMap)
	fmt.Println("-----------------初始化之后-------------")
	key := "中国"
	value, ok := sliceMap[key]
	if !ok {
		value = make([]string, 0, 2)
	}
	value = append(value, "北京", "上海")
	sliceMap[key] = value
	fmt.Println(sliceMap)
}

运行结果

map[]
-----------------初始化之后-------------
map[中国:[北京 上海]]

将Map传递到函数

        在函数间传递Map并不会制造出该映射的副本。当传递Map给函数,并对这个Map做了修改时,所有对这个Map的引用都会察觉到这个修改。

package main

import "fmt"

func main() {
	disc := map[string]int{"1": 10, "2": 20, "3": 30, "4": 0, "5": 0}

	//遍历map中所有值
	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}
	test(disc)

	fmt.Println("--------------处理后-----------------")
	for k, v := range disc {
		fmt.Printf("key=%s,value=%d\n", k, v)
	}

}

func test(m map[string]int) {
	m["2"] = 40
}

运行结果

 印证:遍历map时的元素顺序与添加键值对的顺序无关。而且map是引用类型

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小柏ぁ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值