zoukankan      html  css  js  c++  java
  • go-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 声明的举例

    • map 声明的举例:
    var a map[string]string
    var a map[string]int
    var a map[int]string
    var a map[string]map[string]string
    

    注意:声明是不会分配内存的,初始化需要 make ,分配内存后才能赋值和使用。
    案例演示:

    package main
    import (
    	"fmt"
    )
    
    func main() {
    	//map的声明和注意事项 
    	var a map[string]string
    	//在使用map前,需要先make , make的作用就是给map分配数据空间
    	a = make(map[string]string, 10)
    	a["no1"] = "宋江" //ok?
    	a["no2"] = "吴用" //ok?
    	a["no1"] = "武松" //ok?
    	a["no3"] = "吴用" //ok?
    	fmt.Println(a)
    }
    
    • 对上面代码的说明
    1. map 在使用前一定要 make
    2. map 的 key 是不能重复,如果重复了,则以最后这个 key-value 为准
    3. map 的 value 是可以相同的.
    4. map 的 key-value 是无序
    5. make 内置函数数目

    搜狗截图20191024220854

    map的使用

    方式1

    var a map[string]string
    	//在使用map前,需要先make , make的作用就是给map分配数据空间
    	a = make(map[string]string, 10)
    	a["no1"] = "宋江" //ok?
    	a["no2"] = "吴用" //ok?
    	a["no1"] = "武松" //ok?
    	a["no3"] = "吴用" //ok?
    	fmt.Println(a)
    

    方式2

    cities := make(map[string]string)
    	cities["no1"] = "北京"
    	cities["no2"] = "天津"
    	cities["no3"] = "上海"
    	fmt.Println(cities)
    

    方式3

    heroes := map[string]string{
    		"hero1" : "宋江",
    		"hero2" : "卢俊义",
    		"hero3" : "吴用",
    	}
    	heroes["hero4"] = "林冲"
    	fmt.Println("heroes=", heroes)
    

    练习
    演示一个key-value 的value是map的案例
    比如:我们要存放3个学生信息, 每个学生有 name和sex 信息
    思路: map[string]map[string]string

    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"])
    

    搜狗截图20191024221647

    map 的增删改查操作

    package main
    import (
    	"fmt"
    )
    
    func main() {
    	//第二种方式
    	cities := make(map[string]string)
    	cities["no1"] = "北京"
    	cities["no2"] = "天津"
    	cities["no3"] = "上海"
    	fmt.Println(cities)
    
    	//因为 no3这个key已经存在,因此下面的这句话就是修改
    	cities["no3"] = "上海~" 
    	fmt.Println(cities)
    
    	//演示删除
    	delete(cities, "no1")
    	fmt.Println(cities)
    	//当delete指定的key不存在时,删除不会操作,也不会报错
    	delete(cities, "no4")
    	fmt.Println(cities)
    
    
    	//演示map的查找
    	val, ok := cities["no2"]
    	if ok {
    		fmt.Printf("有no1 key 值为%v
    ", val)
    	} else {
    		fmt.Printf("没有no1 key
    ")
    	}
    
    	//如果希望一次性删除所有的key
    	//1. 遍历所有的key,如何逐一删除 [遍历]
    	//2. 直接make一个新的空间
    	cities = make(map[string]string)
    	fmt.Println(cities)
    
    }
    
    • map 增加和更新:
      map["key"] = value // 如果 key 还没有,就是增加,如果 key 存在就是修改。
    • map 删除:
      说明:
      delete(map,"key") ,delete 是一个内置函数,如果 key 存在,就删除该 key-value,如果 key 不存在,
      不操作,但是也不会报错
    • 细节说明
      如果我们要删除 map 的所有 key ,没有一个专门的方法一次删除,可以遍历一下 key, 逐个删除
      或者 map = make(...),make 一个新的,让原来的成为垃圾,被 gc 回收
    • map 查找:
      对上面代码的说明:
      说明:如果 heroes 这个 map 中存在 "no1" , 那么 findRes 就会返回 true,否则返回 false

    遍历:

    案例演示相对复杂的 map 遍历:该 map 的 value 又是一个 map
    说明:map 的遍历使用 for-range 的结构遍历

    package main
    import (
    	"fmt"
    )
    
    func main() {
    	//使用for-range遍历map
    	//第二种方式
    	cities := make(map[string]string)
    	cities["no1"] = "北京"
    	cities["no2"] = "天津"
    	cities["no3"] = "上海"
    	
    	for k, v := range cities {
    		fmt.Printf("k=%v v=%v
    ", k, v)
    	}
    
    	fmt.Println("cities 有", len(cities), " 对 key-value")
    
    	//使用for-range遍历一个结构比较复杂的map
    	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.Println("k1=", k1)
    		for k2, v2 := range v1 {
    				fmt.Printf("	 k2=%v v2=%v
    ", k2, v2)
    		}
    		fmt.Println()
    	}
    }
    

    搜狗截图20191024222458

    搜狗截图20191024222609

    map切片

    基本介绍

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

    案例演示

    要求:使用一个 map 来记录 monster 的信息 name 和 age, 也就是说一个 monster 对应一个 map,并
    且妖怪的个数可以动态的增加=>map 切片

    package main
    import (
    	"fmt"
    )
    
    func main() {
    	//演示map切片的使用
    	/*
    	要求:使用一个map来记录monster的信息 name 和 age, 也就是说一个
    	monster对应一个map,并且妖怪的个数可以动态的增加=>map切片
    	*/
    	//1. 声明一个map切片
    	var monsters []map[string]string
    	monsters = make([]map[string]string, 2) //准备放入两个妖怪
    	//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"] = "400"
    	}
    
    	// 下面这个写法越界。
    	// if monsters[2] == nil {
    	// 	monsters[2] = make(map[string]string, 2)
    	// 	monsters[2]["name"] = "狐狸精"
    	// 	monsters[2]["age"] = "300"
    	// }
    
    	//这里我们需要使用到切片的append函数,可以动态的增加monster
    	//1. 先定义个monster信息
    	newMonster := map[string]string{
    		"name" : "新的妖怪~火云邪神",
    		"age" : "200",
    	}
    	monsters = append(monsters, newMonster)
    
    	fmt.Println(monsters)
    }
    

    map 排序

    基本介绍

    1. golang 中没有一个专门的方法针对 map 的 key 进行排序
    2. golang 中的 map 默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出
      可能不一样.
    3. golang 中 map 的排序,是先将 key 进行排序,然后根据 key 值遍历输出即可
    package main
    import (
    	"fmt"
    	"sort"
    )
    
    func main() {
    
    	//map的排序
    	map1 := make(map[int]int, 10)
    	map1[10] = 100
    	map1[1] = 13
    	map1[4] = 56
    	map1[8] = 90
    
    	fmt.Println(map1)
    
    	//如果按照map的key的顺序进行排序输出
    	//1. 先将map的key 放入到 切片中
    	//2. 对切片排序 
    	//3. 遍历切片,然后按照key来输出map的值
    
    	var keys []int
    	for k, _ := range map1 {
    		keys = append(keys, k)
    	}
    	//排序
    	sort.Ints(keys)
    	fmt.Println(keys)
    
    	for _, k := range keys{
    		fmt.Printf("map1[%v]=%v 
    ", k, map1[k])
    	}
    	
    }
    

    map 使用细节

    1. map 是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改原来
      的 map
    2. map 的容量达到后,再想 map 增加元素,会自动扩容,并不会发生 panic,也就是说 map 能动
      态的增长 键值对(key-value)
    3. map 的 value 也经常使用 struct 类型,更适合管理复杂的数据(比前面 value 是一个 map 更好),比如 value 为 Student 结构体
    package main
    import (
    	"fmt"
    )
    func modify(map1 map[int]int) {
    	map1[10] = 900
    }
    
    //定义一个学生结构体
    type Stu struct {
    	Name string
    	Age int
    	Address string
    }
    
    func main() {
    
    	//map是引用类型,遵守引用类型传递的机制,在一个函数接收map,
    	//修改后,会直接修改原来的map
    
    	map1 := make(map[int]int, 2)
    	map1[1] = 90
    	map1[2] = 88
    	map1[10] = 1
    	map1[20] = 2
    	modify(map1)
    	// 看看结果, map1[10] = 900 ,说明map是引用类型
    	fmt.Println(map1) 
    
    
    	//map的value 也经常使用struct 类型,
    	//更适合管理复杂的数据(比前面value是一个map更好),
    	//比如value为 Student结构体 【案例演示,因为还没有学结构体,体验一下即可】
    	//1.map 的 key 为 学生的学号,是唯一的
    	//2.map 的 value为结构体,包含学生的 名字,年龄, 地址
    
    	students := make(map[string]Stu, 10)
    	//创建2个学生
    	stu1 := Stu{"tom", 18, "北京"}
    	stu2 := Stu{"mary", 28, "上海"}
    	students["no1"] = stu1
    	students["no2"] = stu2
    
    	fmt.Println(students)
    
    	//遍历各个学生信息
    	for k, v := range students {
    		fmt.Printf("学生的编号是%v 
    ", k)
    		// fmt.Printf("学生的编号是%v 
    ", v)
    		fmt.Printf("学生的名字是%v 
    ", v.Name)
    		fmt.Printf("学生的年龄是%v 
    ", v.Age)
    		fmt.Printf("学生的地址是%v 
    ", v.Address)
    		fmt.Println()
    	}
    
    }
    

    案例

    1. 使用 map[string]map[string]sting 的 map 类型
    2. key: 表示用户名,是唯一的,不可以重复
    3. 如果某个用户名存在,就将其密码修改"888888",如果不存在就增加这个用户信息,(包括昵称
      nickname 和 密码 pwd)。
    4. 编写一个函数 modifyUser(users map[string]map[string]sting, name string) 完成上述功能
      代码实现
    package main
    import (
    "fmt"
    )
    func modifyUser(users map[string]map[string]string, name string) {
    //判断 users 中是否有 name
    //v , ok := users[name]
    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() {
    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)
    }
    
  • 相关阅读:
    事件的截获
    页面嵌入dom与被嵌入iframe的攻防
    如何在windows下安装JDK
    Java and C# Comparison
    利用hadoop来解决“单表关联”的问题
    Oracle10GODP连接11G数据库,出现ORA
    sql 2005出现错误:数据库 'Twitter' 的事务日志已满。若要查明无法重用日志中的空间的原因,请参阅 sys.databases 中的 log_reuse_wait_desc 列。
    MapReduce 模式、算法和用例
    利用hadoop来解决“共同好友”的问题
    部署hadoop的开发环境
  • 原文地址:https://www.cnblogs.com/ygjzs/p/11779989.html
Copyright © 2011-2022 走看看