GO学习笔记——map(13)

每个语言基本都有类似于map的容器,C++有map和unordered_map,map的底层是红黑树,unordered_map的底层是哈希表。那么GO语言中的map它的底层就是哈希表了。下面来讨论GO语言中的map的使用


定义map

可以用下面的方式直接定义

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	fmt.Println(m1)
}

其中定义的第一行,map表示变量m是一个map,[string]表示它的key是一个string,后面跟着的string表示它的值是一个string,花括号{}内部是给这个map添加的一些元素

另外也可以用make来定义

m2 := make(map[string]string)

上面创建了一个空的map,注意空的map和nil的区别

func main() {
	m2 := make(map[string]string)	//空map
	var m3 map[string]string	//nil

        m2["April"] = "4"	//添加成功
	m3["April"] = "4"	//运行时出错

	fmt.Println(m2)
	fmt.Println(m3)
}

用make创建出来的是一个空map,而如果像下面一行那样只是用var来声明,那么其实这个m3是一个nil,nil是map的默认零值,这个和Slice一样,往nil的map中插入数据会出错

panic: assignment to entry in nil map

所以不推荐使用var来只声明而不定义一个map,声明了还是需要用make来给map定义。

向map中添加元素

添加元素有点像C++的map重载的[]的方法,直接使用[]来像map中添加和修改元素,用过C++的map的应该很好理解

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	fmt.Println(m1)
	m1["April"] = "4"	//添加成功
	fmt.Println(m1)
	m1["January"] = "一月"
	fmt.Println(m1)		//修改成功
}

输出结果

map[January:1 February:2 March:3]
map[January:1 February:2 March:3 April:4]
map[January:一月 February:2 March:3 April:4]    //修改成功

遍历map

range也可以用在对map的遍历,事实上许多容器都可以用range来遍历

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}
    
        m1["April"] = "4"	//添加成功
	for k,v := range m1 {
		fmt.Println(k,v)
	}
}

输出结果

January 1
February 2
March 3
April 4

range同样返回两个值,第一个表示map的key,第二个表示map的value,和数组的使用方式一样,如果我们只想要value,那么需要k的位置需要用下划线_代替。

至于为什么输出的结果顺序为什么不是有序的,即如果是有序的,那么输出的结果是按key的大小排序的(即April,February,March,Month),这里学过C++的应该了解过map和unordered_map的区别,map的底层是红黑树,遍历一棵红黑树的时候,我们遍历的时候是按大小比较遍历的,而GO的map相当于unordered_map,底层是哈希表实现的,哈希表不能保证插入进来的元素的有序性,它是无序的,但是它的插入效率要比红黑树快一点,因此就是牺牲有序性来提升效率。

获取map中的元素

获取元素同样通过[]来获取,只不过注意一下它的返回值。

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}


	month := m1["January"]
	fmt.Println(month)
}

这边通过[]获取到了key为January的value,那么这个时候如果想要获取一个不存在的key的value会怎么样呢?

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}


	month := m1["April"]
	fmt.Println(month)
	fmt.Println(m1)
}

输出结果


map[March:3 January:1 February:2]

输出了一个空串,所以如果key不存在,那么返回的是value的默认零值。我们之后也打印了一下m1,发现m1中并没有这个April。其实学过C++的在这里地方会有一点问题,因为在这种情况下,C++的map中是会将April这个key插入到map中的。

来看一下下面的C++代码

#include <iostream>
#include <map>
using namespace std;

int main(){
    map<string,string> m1;
    m1["January"] = "1";
    m1["February"] = "2";
    m1["March"] = "3";

    for(auto i : m1)
        cout << i.first << ":" << i.second << endl;

    cout << endl;
    string month = m1["April"];
    for(auto i : m1)
        cout << i.first << ":" << i.second << endl;
    return 0;
}

输出结果

February:2
January:1
March:3

April:
February:2
January:1
March:3

可见,GO语言在这个地方和C++就不同了,需要注意,GO只有在真正地执行添加元素的操作才会往map中添加元素,而C++只要使用到对应的key就会往map中添加这个key

另外,如果想要判断key在map中是否存在怎么做呢?GO通过下面的方式来解决

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	month,ok:= m1["April"]
	fmt.Println(month,ok)
	month,ok = m1["January"]
	fmt.Println(month,ok)
}

输出结果

 false
1 true

其实调用[]返回的是两个值,第一个是key对应的value,第二个返回值表示这个key是否存在,是一个bool类型。所以,如果我们只想判断这个key是否存在,就可以用下划线_代替前面的value不接收那个参数

删除map中的元素

删除map中的元素使用内置函数delete

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	month,ok := m1["January"]
	fmt.Println(month,ok)

	delete(m1,"January")

	month,ok = m1["January"]
	fmt.Println(month,ok)
}

输出结果

1 true
 false

这样就把key为January的元素删除了

获取map中元素的个数

获取元素个数使用len内置函数

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	fmt.Println(len(m1))
}

输出结果

3

map是引用类型

func change(m1 map[string]string){
	m1["January"] = "一月"
}

func main() {
	m1 := map[string]string{
		"January" : "1",
		"February" : "2",
		"March" : "3",
	}

	change(m1)
	fmt.Println(m1)
}

输出结果

map[January:一月 February:2 March:3]

因为map是引用类型,所以它作为参数传给函数参数的时候,是引用传递,因此在函数内部对map的改变也会影响到原有的map。

猜你喜欢

转载自blog.csdn.net/lvyibin890/article/details/83343879