package main

import (
	"fmt"
	"sort"
)

// 哈希表是一种巧妙并且实用的数据结构。
// 它是一个无序的key/value对的集合，其中检索、更新或删除对应的value。

// Go中 用map[K]V来表示，其中K和V分别对应Key和Value，
// map中所有的key都有相同的类型，所有的value也有着相同的类型
// 但是 Key和Value之间可以是不同的数据类型

func main() {
	// 使用内置函数可以创建一个map
	//args := make(map[string]int)
	// 也可以指定一些最初的值
	map1 := map[string]int{
		"alice": 12,
		"小明":    13,
		"小红":    15,
	}
	fmt.Println(map1)

	// 可以使用对应的下标访问对应的Value
	fmt.Println(map1["小明"]) // 13

	// 使用内置的delete()函数可以删除map中元素
	delete(map1, "alice")
	fmt.Println(map1)

	// 删除一个不存在的key时，代码也是安全的
	delete(map1, "soul")

	// 在查询key失败时，go会将此key赋0值
	// 所以下面的代码工作正常呢
	map1["bob"] = map1["bob"] + 1
	fmt.Println(map1)
	fmt.Println(map1["qaq"]) // 0
	print("ll")
	// x += y, x++等简短赋值语句在map上也适用
	map1["bob"] += 1
	fmt.Println(map1["bob"]) // 2

	// 但是map中的元素并不是变量，不能对其进行取地址的操作。

	// 可以使用range和for循环遍历map中的K和V
	for name, age := range map1 {
		fmt.Printf("%s is %d\n", name, age)
	}
	// Map的迭代顺序是不确定的，并且不同的哈希函数实现可能导致不同的遍历顺序。
	// 在实践中，遍历的顺序是随机的，每一次遍历的顺序都不相同。
	// 这是故意的，每次都使用随机的遍历顺序可以强制要求程序不会依赖具体的哈希函数实现。
	// 如果要按顺序遍历key/value对，我们必须显式地对key进行排序，
	// 可以使用sort包的Strings函数对字符串slice进行排序。
	var names []string
	for name := range map1 {
		names = append(names, name)
	}
	sort.Strings(names)
	for _, name := range names {
		fmt.Printf("%s is %d\n", name, map1[name])
	}
}
