原创

Go中的map和Java中的HashMap区别

Go中的map也是一个存储key-value,键值对的这么一种数据结构。
我们来看下如何使用:
如何创建一个map?(map是引用类型,默认值是nil,必须用make为其创建才能使用)
创建一个map必须要用make,否则会是nil
格式为: make(map[key类型]value类型) (下面有代码示例)
往Go中的map赋值添加元素用 【 map变量名称[key] = value 】 的方式

示例1:创建map以及添加元素

package main
import "fmt"
func main() {
   //创建一个map必须要用make,否则会是nil
   //格式为:  make(map[key类型]value类型)
   //Java中:   Map<String,Integer> myMap = new HashMap<>();
   myMap := make(map[string]int)
   //往Go中的map赋值添加元素用 【 map变量名称[key] = value 】 的方式
   //区别于Java中的: myMap.put("li_age",20);
   myMap["li_age"] = 20
   myMap["hong_age"] = 30
   //打印一下map
   fmt.Println(myMap)
}

我们从map中取值得格式为: 【 mapValue := map变量名[key]】
当我们填写的key在map中找不到时返回对应的value默认值,int是0,引用类型是nil
当我们的key取不到对应的值,而value的类型是一个int类型,我们如何判断这个0是实际值还是默认值呢
此时我们需要同时取两个值
通过map的key取出两个值,第二个参数为bool类型,false为该值不存在,true为成功取到值

参考下面:
示例2:从map中取值

package main
import "fmt"
func main() {
   //创建一个map必须要用make,否则会是nil
   //格式为:  make(map[key类型]value类型)
   //Java中:   Map<String,Integer> myMap = new HashMap<>();
   myMap := make(map[string]int)
   //往Go中的map赋值添加元素用 【 map变量名称[key] = value 】 的方式
   //区别于Java中的: myMap.put("li_age",20);
   myMap["li_age"] = 20
   myMap["hong_age"] = 30
   //打印一下map
   fmt.Println(myMap)
   //不存在的值
   fmt.Println(myMap["no"])

   //当我们的key取不到对应的值,而value的类型是一个int类型,我们如何判断这个0是实际值还是默认值呢
   //此时我们需要同时取两个值
   //通过map的key取出两个值,第二个参数为bool类型,false为该值不存在,true为成功取到值
   value,existsValue := myMap["no"]
   if !existsValue {
      fmt.Println("此值不存在")
   } else {
      fmt.Printf("value = %d",value)
   }
}

Go中因为返回值可以是两个,所以的map遍历很简单,不像java还得弄一个Iterator对象再逐个获取,它一次两个都能取出来,用for搭配range即可实现。

示例3:遍历

package main
import "fmt"
func main() {
   myMap := make(map[string]int)
   myMap["num1"] = 1
   myMap["num2"] = 2
   myMap["num3"] = 3
   myMap["num4"] = 4
   myMap["num5"] = 5
   myMap["num6"] = 6
   //遍历key,value
   for key,value := range myMap {
      fmt.Println(key,value)
   }
   //写一个参数的时候只取key
   for key := range myMap {
      fmt.Println(key)
   }
   //如果只想取value,就需要用到之前的_标识符进行占位丢弃
   for _,value := range myMap {
      fmt.Println(value)
   }
}

删除函数:用内置函数delete删除
示例4:删除map元素

package main
import "fmt"
func main() {
   myMap := make(map[string]int)
   myMap["num1"] = 1
   myMap["num2"] = 2
   myMap["num3"] = 3
   myMap["num4"] = 4
   myMap["num5"] = 5
   myMap["num6"] = 6
   //第二个参数为删除的key
   delete(myMap,"num6")
   //此时已经没有值了,默认值为0
   fmt.Println(myMap["num6"])
}

在Java中有一些复杂的Map类型,比如:
Map<String,Map<String,Object>> data = new HashMap<>();

实际上,在Go语言中,也有复杂的类型,我们举几个代码示例

示例5:

package main
import "fmt"
func main() {
   //由map组成的切片
   //第一部分 make[] 声明切片
   //第二部分 map[string]int  声明该切片内部装的单个类型是map
   //第三部分 参数 5 表示该切片的长度和容量都是5
   //长度是用索引能取到第几个元素,索引不能超过长度-1,分配长度后都是默认值,int是0,引用类型是nil
   //容量至少比长度大,能索引到几个+未来可添加元素个数(目前没有任何东西,看不见)= 切片容量
   //make([]切片类型,切片长度,切片容量)
   //make([]切片类型,切片长度和容量等同)
   slice := make([]map[string]int,5,10)
   slice0 := make([]map[string]int,0,10)
   //我们看看打印的东西
   fmt.Println("slice=",slice)
   fmt.Println("slice=0",slice0)

   ///*   先看这段
   //因为有5个长度,所以初始化了5个map,但是map没有通过make申请内容空间,所以报错nil map
   //slice[0]["age"] = 10;//报错
   //下面不报错
   slice[0] = make(map[string]int,10)
   slice[0]["age"] = 19
   fmt.Println(slice[0]["age"])
   //*/
}

输出结果:
slice= [map[] map[] map[] map[] map[]]
slice=0 []
19

接下来继续看代码:

package main
import "fmt"
func main() {
   //由map组成的切片
   //第一部分 make[] 声明切片
   //第二部分 map[string]int  声明该切片内部装的单个类型是map
   //第三部分 参数 5 表示该切片的长度和容量都是5
   //长度是用索引能取到第几个元素,索引不能超过长度-1,分配长度后都是默认值,int是0,引用类型是nil
   //append元素到切片时,是添加到最末尾的位置,当元素未超过容量时,都是用的同一个底层数组
   //超过容量时会返回一个新的数组
   //make([]切片类型,切片长度,切片容量)
   //make([]切片类型,切片长度和容量等同)
   slice := make([]map[string]int,5,10)
   slice0 := make([]map[string]int,0,10)
   //我们看看打印的东西
   fmt.Println("slice=",slice)
   fmt.Println("slice=0",slice0)

   /*   先看这段
   //因为有5个长度,所以初始化了5个map,但是map没有通过make申请内容空间,所以报错nil map
   //slice[0]["age"] = 10;//报错
   //下面不报错
   slice[0] = make(map[string]int,10)
   slice[0]["age"] = 19
   fmt.Println(slice[0]["age"])
   */
}

输出:
panic: assignment to entry in nil map

看下面这个报错:

package main
import "fmt"
func main() {
   //由map组成的切片
   //第一部分 make[] 声明切片
   //第二部分 map[string]int  声明该切片内部装的单个类型是map
   //第三部分 参数 5 表示该切片的长度和容量都是5
   //长度是用索引能取到第几个元素,索引不能超过长度-1,分配长度后都是默认值,int是0,引用类型是nil
   //append元素到切片时,是添加到最末尾的位置,当元素未超过容量时,都是用的同一个底层数组
   //超过容量时会返回一个新的数组
   //make([]切片类型,切片长度,切片容量)
   //make([]切片类型,切片长度和容量等同)
   slice := make([]map[string]int,5,10)
   slice0 := make([]map[string]int,0,10)
   //我们看看打印的东西
   fmt.Println("slice=",slice)
   fmt.Println("slice=0",slice0)

   //因为有5个长度,所以初始化了5个map,但是map没有通过make申请内容空间,所以报错nil map
   //slice[0]["age"] = 10;//报错
   //下面不报错
   slice[0] = make(map[string]int,10)
   slice[0]["age"] = 19
   fmt.Println(slice[0]["age"])
   //因为初始化了0个长度,所以索引取不到值,报index out of range
   slice0[0]["age"] = 10;
}

输出:
slice= [mappanic: runtime error: index out of range

接下来我们看一个:类似于Java中常用的map类型

package main
import "fmt"
func main() {
   //类似于Java中的Map<String,HashMap<String,Object>>
   var myMap = make(map[string]map[string]interface{},10)
   fmt.Println(myMap)
   //记得make
   myMap["li_ming_id_123"] = make(map[string]interface{},5)
   myMap["li_ming_id_123"]["school"] = "清华大学"

   fmt.Println(myMap)
}

输出:
map[]
map[li_ming_id_123:map[school:清华大学]]

本文链接地址:http://ysxbohui.com/article/191

正文到此结束