key为什么是无序的

《Go 程序员面试笔试宝典》 给出的解释:

map 在扩容后,会发生 key 的搬迁,原来落在同一个 bucket 中的 key,搬迁后,有些 key 就要远走高飞了(bucket 序号加上了 2^B)。而遍历的过程,就是按顺序遍历 bucket,同时按顺序遍历 bucket 中的 key。搬迁后,key 的位置发生了重大的变化,有些 key 飞上高枝,有些 key 则原地不动。这样,遍历 map 的结果就不可能按原来的顺序了。

当然,如果我就一个 hard code 的 map,我也不会向 map 进行插入删除的操作,按理说每次遍历这样的 map 都会返回一个固定顺序的 key/value 序列吧。的确是这样,但是 Go 杜绝了这种做法,因为这样会给新手程序员带来误解,以为这是一定会发生的事情,在某些情况下,可能会酿成大错。

当然,Go 做得更绝,当我们在遍历 map 时,并不是固定地从 0 号 bucket 开始遍历,每次都是从一个随机值序号的 bucket 开始遍历,并且是从这个 bucket 的一个随机序号的 cell 开始遍历。这样,即使你是一个写死的 map,仅仅只是遍历它,也不太可能会返回一个固定序列的 key/value 对了。

多说一句,“迭代 map 的结果是无序的”这个特性是从 go 1.0 开始加入的。

总结一下:

  • Go的 map 是基于哈希表实现,而不是红黑树,故遍历时天然不具备有序性
  • 遍历map时,go随机挑选 bucket,并且从 bucket 随机序号的 cell 开始遍历,故无序且每次遍历结果都不一样
  • 扩容会导致 key 的位置发生变化,会影响遍历的 key 的顺序
Copyright © CoffeeChat 2020 all right reserved,powered by Gitbook该文件修订时间: 2023-05-31 16:34:35

results matching ""

    No results matching ""