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的声明举例
    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() {
        var a map[string]string
        // 在使用map前,需要先make,make的作用就是给map分配数据空间
        a = make(map[string]string,10)
        a["name1"]="bingle1"
        a["name2"]="bingle2"
        a["name3"]="bingle3"
        a["name4"]="bingle4"
        fmt.Println(a)
    }

    执行结果为:

    map[name1:bingle1 name2:bingle2 name3:bingle3 name4:bingle4]

    对上面代码的说明:

      1、map 在使用前一定要 make

      2、map 的 key 是不能重复,如果重复了,则以最后这个 key-value 为准

      3、map 的 value 是可以相同的.

      4、map 的 key-value 是无序、

      5、make 内置函数数目

      内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其实第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针,其具体结果取决于具体的类型:

      切片:size指定了其长度,该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;它必须不小于其长度,因此make([]int 0, 10)会分配一个长度为0,容量为10的切片。

    map的使用

    方式1: 

    package main
    
    import "fmt"
    
    func main() {
        var a map[string]string
        // 在使用map前,需要先make,make的作用就是给map分配数据空间
        a = make(map[string]string,10)
        a["name1"] = "bingle1"
        a["name2"] = "bingle2"
        a["name3"] = "bingle3"
        a["name4"] = "bingle4"
        fmt.Println(a)
    }

    方式 2:

    package main
    
    import "fmt"
    
    func main() {
        names :=make(map[string]string)
        names["name1"] ="bingle1"
        names["name2"] ="bingle2"
        names["name3"] ="bingle3"
        names["name4"] ="bingle4"
        fmt.Println(names)
    }

    方式 3:

    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        names["name2"] = "bingle222222"
        fmt.Println("names = ", names)
    }

    map的增删改查操作

    1、map的增加和更新:

      map["key"] = value //如果 key 还没有,就是增加,如果 key 存在就是修改。
    2、map删除:
      delete(map,"key") ,delete 是一个内置函数,如果 key 存在,就删除该 key-value,如果 key 不存在,不操作,但是也不会报错

    内建函数delete按照指定的键将元素从映射中删除,若 m 为 nil 或者 无此元素,delete不进行操作.

    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        delete(names,"name1")
        fmt.Println("names = ", names)
    }

    细节说明:

      如果我们要删除 map 的所有 key ,没有一个专门的方法一次删除,可以遍历一下 key, 逐个删除或者 map = make(...),make 一个新的,让原来的成为垃圾,被 gc 回收

    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        names = make(map[string]string)
        fmt.Println("names = ", names)
    }

    3、map查找

    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        val1,ok1 := names["name1"]
        val2,ok2 := names["name1111"]
        if ok1 {
            fmt.Printf("有name1 key 值为 %v 
    ",val1)
        }else {
            fmt.Printf("没有name1 key值")
        }
        if ok2 {
            fmt.Printf("有name2 key 值为 %v 
    ",val2)
        }else {
            fmt.Printf("没有name2 key值")
        }
    }

    对上面代码说明:说明:如果 heroes 这个 map 中存在 "no1" , 那么 findRes 就会返回 true,否则返回 false

    map遍历

    说明:map 的遍历使用 for-range 的结构遍历
    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        for k, v := range names {
            fmt.Printf("k = %v ,v = %v 
    ", k, v)
        }
    }

    map的长度

    内置 len 返回 v 的长度,这取决于具体类型:

      数组:v 中元素的数量

      数组指针:*v 中元素的数量(v 为 nil 的时候panic)

      切片、映射:v 中元素的数量,若 v 为 nil ,len(v) 为零

      字符串:v 中字节的数量

      通道:通道缓存中队列(未读取)元素的数量,若 v 为 nil ,len(v) 为零

    package main
    
    import "fmt"
    
    func main() {
        names := map[string]string{
            "name1": "bingle1",
            "name2": "bingle2",
            "name3": "bingle3",
            "name4": "bingle4",
        }
        fmt.Println(len(names))
    }

    map切片

    基本介绍:

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

    案例:

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

    package main
    import (
        "fmt"
    )
    
    func main() {
        //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"
        "math/rand"
        "sort"
        "time"
    )
    
    func main() {
        rand.Seed(time.Now().UnixNano()) //初始化随机数种子
    
        var scoreMap = make(map[string]int, 200)
    
        for i := 0; i < 100; i++ {
            key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
            value := rand.Intn(100)          //生成0~99的随机整数
            scoreMap[key] = value
        }
        //取出map中的所有key存入切片keys
        var keys = make([]string, 0, 200)
        for key := range scoreMap {
            keys = append(keys, key)
        }
        //对切片进行排序
        sort.Strings(keys)
        //按照排序后的key遍历map
        for _, key := range keys {
            fmt.Println(key, scoreMap[key])
        }
    }

    map 使用细节

    1、map 是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改原来的 map

    package main
    
    import (
        "fmt"
        "math/rand"
        "sort"
        "time"
    )
    
    func modify(scoreMap map[string]int) {
        scoreMap["stu01"] = 999
    }
    
    func main() {
        rand.Seed(time.Now().UnixNano()) //初始化随机数种子
    
        var scoreMap = make(map[string]int, 200)
    
        for i := 0; i < 100; i++ {
            key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串
            value := rand.Intn(100)          //生成0~99的随机整数
            scoreMap[key] = value
        }
        //取出map中的所有key存入切片keys
        var keys = make([]string, 0, 200)
        for key := range scoreMap {
            keys = append(keys, key)
        }
        //对切片进行排序
        sort.Strings(keys)
        //按照排序后的key遍历map
        for _, key := range keys {
            fmt.Println(key, scoreMap[key])
        }
        fmt.Println("==============")
        modify(scoreMap)
        for _, key := range keys {
            fmt.Println(key, scoreMap[key])
        }
    }

    2、map 的容量达到后,再想 map 增加元素,会自动扩容,并不会发生 panic,也就是说 map 能动态的增长 键值对(key-value)

    3、map 的 value 也经常使用 struct 类型,更适合管理复杂的数据(比前面 value 是一个 map 更好)

      比如 value 为 Student 结构体

    package main
    
    import "fmt"
    
    // 定义一个学生结构体
    type Student struct {
        Name string
        Age int
        Address string
    }
    
    func main() {
        students := make(map[string]Student,10)
        stu1 := Student{"bingel1", 18, "北京"}
        stu2 := Student{"bingel2", 28, "上海"}
        students["stu1"] = stu1
        students["stu2"] = stu2
    
        fmt.Println(students)
        //遍历各个学生信息
        for k, v := range students {
            fmt.Printf("学生的编号是%v 
    ", k)
            fmt.Printf("学生的名字是%v 
    ", v.Name)
            fmt.Printf("学生的年龄是%v 
    ", v.Age)
            fmt.Printf("学生的地址是%v 
    ", v.Address)
            fmt.Println()
        }
    }

  • 相关阅读:
    消息队列优缺点及各种MQ对比
    反射详解
    Tomcat线程模型及调优
    Tomcat结构及类加载机制
    Spring AOP
    Spring IOC
    Spring介绍
    SpringMVC介绍
    Mybatis介绍
    Ajax笔记(一)
  • 原文地址:https://www.cnblogs.com/taotaozhuanyong/p/14649012.html
Copyright © 2011-2022 走看看