Go语言 映射(map)
Go语言 映射(map)
1. 什么是 map
2. 创建 map
3. 访问 map
4. nil map和空map
5. map中元素的返回值
6. len()和delete()
7. 测试map中元素是否存在
8. 迭代遍历 map
9. 获取map中所有的key
10. 传递map给函数
1. 什么是 map
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值
Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的
Map 是引用类型,必须初始化才能使用。其中,key的类型除了切片等引用类型,其他类型都可以;而value则可使用所有类型的值
2. 创建 map
可以通过make()创建map,它会先创建好底层数据结构,然后再创建map,并让map指向底层数据结构
my_map := make(map[string]int) [string]表示map的key的数据类型
int表示key对应的值
直接通过大括号创建并初始化赋值:
// 空map
my_map := map[string]string{} // 初始化赋值
my_map := map[string]string{"Red": "#da1337","Orange": '#e95a22"} // 格式化赋值
my_map := map[string]int{
"Java":11,
"Perl":8,
"Python":13, // 注意结尾的逗号不能少
}
注意:
其中map的key可以是任意内置的数据类型(如int),或者其它可以通过 == 进行等值比较的数据类型,如interface和指针可以,slice、数组、map、struct类型都不能作为key ,并且key必须唯一。
但value基本可以是任意类型,例如嵌套一个slice到map中:
my_map := map[string][]int{}
3. 访问 map
访问map中的元素时,指定它的key即可,注意string类型的key必须加上引号:
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 10,
"2": 20,
"3": 30,
"4": 40,
}
//访问
fmt.Println(my_map["1"])
fmt.Println(my_map)
fmt.Println("")
//赋值已有的key & value
my_map["2"] = 50
fmt.Println(my_map["2"])
fmt.Println(my_map)
fmt.Println("")
//赋值新的key&value
my_map["5"] = 66
fmt.Println(my_map["5"])
fmt.Println(my_map)
}
//输出结果
10
map[1:10 2:20 3:30 4:40]
50
map[1:10 2:50 3:30 4:40]
66
map[1:10 2:50 3:30 4:40 5:66]
4. nil map和空map
空map是不做任何赋值的map:
// 空map
package main import "fmt" func main() {
my_map := map[string]string{} fmt.Println(my_map)
} //输出结果
map[]
nil map,它将不会做任何初始化,不会指向任何数据结构:
// nil map
var my_map map[string]string
nil map和empty map的关系,就像nil slice和empty slice一样,两者都是空对象,未存储任何数据,但前者不指向底层数据结构,后者指向底层数据结构,只不过指向的底层对象是空对象。
使用println输出看下即可知道:
package main
func main() {
var nil_map map[string]string
println(nil_map)
emp_map := map[string]string{}
println(emp_map)
}
输出结果:
0x0
0xc04204de38
所以,map类型实际上就是一个指针。
5. map中元素的返回值
当访问map中某个元素的时候,有两种返回值的格式:
value := my_map["key"]
value,exists := my_map["key"]
第一种很好理解,就是检索map中key对应的value值。如果key不存在,则value返回值对应数据类型的0。例如int为数值0,布尔为false,字符串为空""。
第二种不仅返回key对应的值,还根据key是否存在返回一个布尔值赋值给exists变量。所以,当key存在时,value为对应的值,exists为true;当key不存在,value为0(同样是各数据类型所代表的0),exists为false。
看下例子:
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 10,
"2": 20,
"3": 30,
"4": 40,
}
a := my_map["1"]
b, exists1 := my_map["2"]
c, exists2 := my_map["5"]
fmt.Println(a)
fmt.Println(b, exists1)
fmt.Println(c, exists2)
}
上面将输出如下结果:
10
20 true
0 false
在Go中设置类似于这种多个返回值的情况很多,即便是自己编写函数也会经常设置它的exists属性。
6. len()和delete()
len()函数用于获取map中元素的个数,即有多个少key。delete()用于删除map中的某个key。
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 10,
"2": 20,
"3": 30,
"4": 40,
}
fmt.Printf("删除前长度为%d\n", len(my_map))
delete(my_map, "1")
fmt.Printf("删除后长度为%d", len(my_map))
}
//输出结果如下
删除前长度为4
删除后长度为3
7. 测试map中元素是否存在
两种方式可以测试map中是否存在某个key:
① 根据map元素的第二个返回值来判断
② 根据返回的value是否为0(不同数据类型的0不同)来判断
方式一:直接访问map中的该元素,将其赋值给两个变量,第二个变量就是元素是否存在的修饰变量。
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 10,
"2": 20,
"3": 30,
"4": 40,
}
//方法1
/* value, exists := my_map["1"]
if exists {
fmt.Println("存在", value)
}
*/
//方法2
if value, exists := my_map["1"]; exists {
fmt.Printf("值存在, value=%d", value)
}
}
//输出结果如下
值存在, value=10
方式二:根据map元素返回的value判断。因为该map中的value部分是int类型,所以它的0是数值的0。
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 10,
"2": 20,
"3": 30,
"4": 40,
}
value := my_map["5"]
if value == 0 {
fmt.Println("不存在")
}
}
//输出结果如下
不存在
如果map的value数据类型是string,则判断是否为空:
package main
import "fmt"
func main() {
my_map := map[string]string{
"1": "book",
"2": "games",
"3": "computer",
}
value := my_map["5"]
if value == "" {
fmt.Println("不存在")
}
}
//输出结果如下
不存在
由于map中的value有可能本身是存在的,但它的值为0,这时就会出现误判断。例如下面的"3",它已经存在,但它对应的值为0
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 22,
"2": 11,
"3": 0,
}
value := my_map["3"]
if value == 0 {
fmt.Println("不存在")
}
}
//输出结果如下
不存在
所以,应当使用第一种方式进行判断元素是否存在。
8. 迭代遍历 map
因为map是key/value类型的数据结构,key就是map的index,所以range关键字对map操作时,将返回key和value。
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 22,
"2": 11,
"3": 0,
"4": 55,
"5": 66,
}
for k, v := range my_map {
fmt.Printf("key=%s, value=%d\n", k, v)
}
}
//输出结果如下
key=1, value=22
key=2, value=11
key=3, value=0
key=4, value=55
key=5, value=66
如果range迭代map时,只给一个返回值,则表示迭代map的key:
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 22,
"2": 11,
"3": 0,
"4": 55,
"5": 66,
}
for key := range my_map {
fmt.Println("key=", key)
}
}
//输出结果
key= 1
key= 2
key= 3
key= 4
key= 5
9. 获取map中所有的key
Go中没有提供直接获取map所有key的函数。所以,只能自己写,方式很简单,range遍历map,将遍历到的key放进一个slice中保存起来。
package main
import "fmt"
func main() {
my_map := map[string]int{
"Java": 11,
"Perl": 8,
"Python": 13,
"Shell": 23,
}
// 保存map中key的slice
// slice类型要和map的key类型一致
keys := make([]string,0,len(my_map))
// 将map中的key遍历到keys中
for map_key,_ := range my_map {
keys = append(keys,map_key)
}
fmt.Println(keys)
}
注意上面声明的slice中要限制长度为0,否则声明为长度4、容量4的slice,而这4个元素都是空值,而且后面append()会直接对slice进行一次扩容,导致append()后的slice长度为map长度的2倍,前一半为空,后一般才是map中的key。
10. 传递map给函数
map是一种指针,所以将map传递给函数,仅仅只是复制这个指针,所以函数内部对map的操作会直接修改外部的map。
例如,test()用于给map的key对应的值加1。
package main
import "fmt"
func main() {
my_map := map[string]int{
"1": 22,
"2": 11,
"3": 0,
"4": 55,
"5": 66,
}
fmt.Println("修改之前key=", my_map["3"])
fmt.Println(my_map)
fmt.Println("")
test(my_map, "3")
fmt.Println("修改之后key=", my_map["3"])
fmt.Println(my_map)
}
func test(m map[string]int, key string) {
m[key] += 1
}
//输出结果如下
修改之前key= 0
map[1:22 2:11 3:0 4:55 5:66]
修改之后key= 1
map[1:22 2:11 3:1 4:55 5:66]
Go语言 映射(map)的更多相关文章
- VIM键盘映射 (Map)~转载
VIM键盘映射 (Map) 设置键盘映射 使用:map命令,可以将键盘上的某个按键与Vim的命令绑定起来.例如使用以下命令,可以通过F5键将单词用花括号括起来: :map <F5> i{e ...
- 图像映射map
<map>标签:带有可点击区域的图像映射 定义一个客户端图像映射.图像映射(image-map)指带有可点击区域的一幅图像. 效果图: 点击相应蓝色标签可进入详情页面浏览. 代码: < ...
- <顶>vim快捷键映射Map使用
问题描述: 使用vim中的快捷键映射map,可以自定义快捷键 问题解决: (1)vim模式 (2)map前缀 (3)删除映射Map (4)使用示例 (5)查看快捷键映射 命令行---:verbose ...
- java映射(map用法)
主要分两个接口:collection和Map 主要分三类:集合(set).列表(List).映射(Map)1.集合:没有重复对象,没有特定排序方式2.列表:对象按索引位置排序,可以有重复对象3.映射: ...
- JAVA核心技术I---JAVA基础知识(映射Map)
一:映射Map分类 二:Hashtable(同步,慢,数据量小) –K-V对,K和V都不允许为null –同步,多线程安全 –无序的 –适合小数据量 –主要方法:clear, contains/con ...
- Hibernate映射Map属性2
Hibernate在映射Map属性时生成映射文件.需要注意的一些地方.下面是我的一个例子. Java类如下 public class NameAndNumber { private Integer i ...
- Hibernate映射Map属性
看到一篇Hibernate 映射Map属性的文章挺好的转载一下原地址:http://blog.sina.com.cn/s/blog_86f4502c0101fs1x.html Map集合属于有序集合, ...
- 元组Tuple、数组Array、映射Map
一.元组Tuple 元组Tuple是不同类型的值的聚集,元组的值将单个的值包含在圆括号中来构成,元组可以包含一个不同类型的元素 如 val riple = (100, "Scala" ...
- go语言之map
go语言的map就相当于python的dict 1.map的初始化 //创建map //k的类型是int,v的类型是string var test25_1 map[int]string fmt.Pri ...
随机推荐
- CentOS 7.5关闭FireWall 和SELinux图文详解
CentOS 7.5关闭FireWall 和SELinux图文详解 1. 环境 CentOS 7.5 2. 关闭FireWall和SELinux 2.1 FireWall 使用systemctl st ...
- [动态规划] LeetCode 2055. 蜡烛之间的盘子
LeetCode 2055 蜡烛之间的盘子 前言: 这个题做的时间略长了,开始的时候打算先定位两个端点的蜡烛,之后在遍历其中的盘子,结果不言而喻,必time limit了,之后就预处理了前x的蜡烛间盘 ...
- 【面经】Python面试的16个高频问题
(一)Python 是如何进行内存管理的? 答:从三个方面来说,一对象的引用计数机制,二垃圾回收机制,三内存池机制 ⒈对象的引用计数机制 Python 内部使用引用计数,来保持追踪内存中的对象,所有对 ...
- 程序设计基础·Java学习笔记·面向对象(上)
Java程序设计基础之面向对象(上) (自适应学习进度而进行记录的笔记,希望有一些小小的用处吧(^∀^●)ノシ) (新人上路,望多指教,如有错误,望指正,万分感谢(o゚v゚)ノ) 目录 一.面向对象 ...
- asp.net多语言网站的完整解决方案
应用场景:通过前端切换网站使用英语.中文两种语言. 解决思路:ResourceManager会通过当前线程区域性信息,读取对应的Resource文件,从而达到切换语言的效果,其实质是是在切换当前线程的 ...
- ZYNQ使用ymodem协议传输文件
SDK: V2014.4 协议: Ymodem 工具: USB转UART转接线.xshell6软件 可实现各种文件传输,大小不限,只是速度很慢 参考原代码如下: /****************** ...
- [转载]Linux后门整理合集(脉搏推荐)
我在思考要不要联系下....都禁止转载了.... 简介 利用 Unix/Linux 自带的 Bash 和 Crond 实现远控功能,保持反弹上线到公网机器. 利用方法 先创建 /etc/xxxx 脚本 ...
- P5017 [NOIP2018 普及组] 摆渡车
P5017 [NOIP2018 普及组] 摆渡车 题目 P5017 思路 将实际问题抽象后,不难发现这是一个 区间 \(DP\) 我们不妨认为时间是一条数轴,每名同学按照到达时刻分别对应数轴上可能重合 ...
- J20航模遥控器开源项目系列教程(四)PCB打印 | 嘉立创PCB下单教程,5元顺丰包邮解君愁!
我们的开源宗旨:自由 协调 开放 合作 共享 拥抱开源,丰富国内开源生态,开展多人运动,欢迎加入我们哈~ 和一群志同道合的人,做自己所热爱的事! 项目开源地址:https://github.com/J ...
- 洛谷P1049 [NOIP2001 普及组] 装箱问题
本题就是一个简单的01背包问题 1.因为每个物品只能选一次,而且要使箱子的剩余空间为最小.所以可以确定属性为 MAX 2.由于是从n个物品里面选i个物品 那么就是选出的i个物品的空间总和要尽可能的 ...