Go语言之自定义集合Set

2020-01-28 12:04:18丽君

一、Go语言实战——自定义集合Set

在Go语言中有作为Hash Table实现的字典(Map)类型,但标准数据类型中并没有集合(Set)这种数据类型。比较 Set 和 Map 的主要特性,有类似特性如下:

    它们中的元素都是不可重复的。

    它们都只能用迭代的方式取出其中的所有元素。

    对它们中的元素进行迭代的顺序都是与元素插入顺序无关的,同时也不保证任何有序性。

但是,它们之间也有一些区别,如下:

Set 的元素是一个单一的值,而 Map 的元素则是一个键值对。

Set 的元素不可重复指的是不能存在任意两个单一值相等的情况。Map的元素不可重复指的是任意两个键值对中的键的值不能相等。

从上面的特性可知,可以把集合类型(Set)作为字典类型(Map)的一个简化版本。也就是说,可以用 Map 来编写一个 Set 类型的实现。实际上,在Java语言中,java.util.HashSet 类就是用 java.util.HashMap 类作为底层支持的。所以这里就从HashSet出发,逐步抽象出集合Set。

1. 定义HashSet

首先,在工作区的 src 目录的代码包 basic/set(可以自行定义,但后面要保持一致)中,创建一个名为 hash_set.go 的源码文件。

根据代码包 basic/set 可知,源码文件 hash_set.go 的包声明语句(关于这个一些规则可以看前面的系列博文)如下:

package set

上面提到可以将集合类型作为字典类型的一个简化版本。现在我们的 HashSet 就以字典类型作为其底层的实现。HashSet 声明如下:


type HashSet struct {
  m map[interface{}]bool
}

如上声明 HashSet 类型中的唯一的字段的类型是 map[interface{}]bool。选择这样一个字典类型是因为通过将字典 m 的键类型设置为 interface{},让 HashSet 的元素可以是任何类型的,因为这里需要使用 m 的值中的键来存储 HashSet 类型的元素值。那使用 bool 类型作为 m 的值的元素类型的好处如下:

从值的存储形式的角度看,bool 类型值只占用一个字节。

从值的表示形式的角度看,bool 类型的值只有两个—true 和 false。并且,这两个值度都是预定义常量。

把 bool 类型作为值类型更有利于判断字典类型值中是否存在某个键。例如:如果在向 m 的值添加键值对的时候总是以 true 作为其中的元素的值,则索引表达式 m[“a”] 的结果值总能体现出在m的值中是否包含键为“a”的键值对。对于 map[interface{}]bool 类型的值来说,如下:


if m["a"] {// 判断是否m中包含键为“a”的键值对
  //省略其他语句
}