Go-映射类型详解(遍历、增删改查、判断相等、内存等)

目录

介绍

声明

方式1

方式2

初始化

添加/修改

删除

查找

内存

遍历

for range

排序

相等

全部代码

截图

注意

参考


介绍

  • 引用类型
  • Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索value。
  • key 类似于索引,指向数据的值,key必须可以使用==运算符来比较,不能重复。
  • Map 是使用 hash 表来实现的。
  • map自动扩容

声明

方式1

var map 变量名 map[key_type]value_type

代码

	var m map[string]string

方式2

make函数

func make(Type, size IntegerType) Type 

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

映射:初始分配的创建取决于size,但产生的映射长度为0。size可以省略,这种情况下就会分配一个小的起始大小。

map的键必须是可以通过操作符== 来比较的数据类型。int、布尔、string、或包含前面的struct、数组等

声明时直接make

var 变量名 = make(map[key_type][value_type])

 代码

	var m1 = make(map[string]string,5)

初始化

key:value形式,添加到花括号中。

代码

	m2 := map[string]string{"野王":"赵云"}

添加/修改

map[key] = value形式,没有会添加,有了会覆盖。

代码

	m1["上官"] = "言为心声"
	m1["婉儿"] = "字为心画"
	m2["野王"] = "老虎"
	m2["上单"] = "吕布"

删除

func delete(m map[Type]Type1, key Type)

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

	delete(m1,"上官")

清空:重新make,没有其他语言类似clear的函数

查找

m[key]返回值和是否存在(bool类型)

	val,flag := m2["野王"]
	if flag{
		fmt.Println("野王:",val)
	}

内存

查看源码

src->runtime->map.go

// A header for a Go map.
type hmap struct {
	// Note: the format of the hmap is also encoded in cmd/compile/internal/gc/reflect.go.
	// Make sure this stays in sync with the compiler's definition.
	count     int // # live cells == size of map.  Must be first (used by len() builtin)
	flags     uint8
	B         uint8  // log_2 of # of buckets (can hold up to loadFactor * 2^B items)
	noverflow uint16 // approximate number of overflow buckets; see incrnoverflow for details
	hash0     uint32 // hash seed

	buckets    unsafe.Pointer // array of 2^B Buckets. may be nil if count==0.
	oldbuckets unsafe.Pointer // previous bucket array of half the size, non-nil only when growing
	nevacuate  uintptr        // progress counter for evacuation (buckets less than this have been evacuated)

	extra *mapextra // optional fields
}
// A bucket for a Go map.
type bmap struct {
	// tophash generally contains the top byte of the hash value
	// for each key in this bucket. If tophash[0] < minTopHash,
	// tophash[0] is a bucket evacuation state instead.
	tophash [bucketCnt]uint8
	// Followed by bucketCnt keys and then bucketCnt elems.
	// NOTE: packing all the keys together and then all the elems together makes the
	// code a bit more complicated than alternating key/elem/key/elem/... but it allows
	// us to eliminate padding which would be needed for, e.g., map[int64]int8.
	// Followed by an overflow pointer.
}

是哈希表实现,拉链法解决冲突。

遍历

for range

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

注意:由于是无序的,go的设计者将遍历做了随机化处理,可就是说两次遍历的结果很可能不一样

排序

对key排序,然后遍历

	m2["野王2"] = "赵云"
	m2["野王3"] = "玛玛哈哈"
	m2["上单2"] = "马超"
	keys := []string{}
	for key,_ := range m2{
		keys = append(keys, key)
	}
	sort.Strings(keys)
	fmt.Println("上单和野王排行榜:")
	for _,key := range keys{
		fmt.Println(key,m2[key])
	}

注意:不是线程安全的,如果需要线程安全的,可以使用sync/Map,等到包的那一节会详细展开。

相等

和slice一样,map之间不能使用==直接比较,map可以和nil使用==比较,我们可以使用循环来判断。

	ok := func(m1,m2 map[string]string) bool{
		if len(m1) != len(m2){
			return false
		}
		for k,v := range m1{
			if v2,ok := m2[k]; !ok || v!=v2{
				return false
			}
		}
		return true
	} (m1,m2)
	fmt.Println("m1和m2相等?",ok)

全部代码

package main

import (
	"fmt"
	"sort"
)

func main() {
	//-------------声明---------------
	var m map[string]string
	//----------声明并分配空间------
	var m1 = make(map[string]string,5)
	m2 := map[string]string{"野王":"赵云"}
	//---------添加和修改---------------
	m1["上官"] = "言为心声"
	m1["婉儿"] = "字为心画"
	m2["野王"] = "老虎"
	m2["上单"] = "吕布"
	fmt.Println("m m1 m2:",m,m1,m2)
	//----------删除-------------------
	delete(m1,"上官")
	fmt.Println("m1:",m1)
	//------------查找-------------
	val,flag := m2["野王"]
	if flag{
		fmt.Println("野王:",val)
	}
	//------------遍历-------------
	for key,value := range m2{
		fmt.Println(key,value)
	}
    //------------排序------------
	m2["野王2"] = "赵云"
	m2["野王3"] = "玛玛哈哈"
	m2["上单2"] = "马超"
	keys := []string{}
	for key,_ := range m2{
		keys = append(keys, key)
	}
	sort.Strings(keys)
	fmt.Println("上单和野王排行榜:")
	for _,key := range keys{
		fmt.Println(key,m2[key])
	}
}

截图

注意

  • key必须可以使用==比较,所以,数组是可以作为key的,但切片不行,类似于Python中的tuple和list
  • 向map存数据前需要make或初始化,仅使用var声明的是不行的,仅声明的话,那是nil

参考

更多Go相关内容:Go-Golang学习总结笔记

有问题请下方评论,转载请注明出处,并附有原文链接,谢谢!如有侵权,请及时联系。如果您感觉有所收获,自愿打赏,可选择支付宝18833895206(小于),您的支持是我不断更新的动力。

相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页