//方法Elements用于生成快照
func (set *HashSet) Elements() []interface{} {
initialLen := len(set.m)//获取HashSet中字段m的长度,即m中包含元素的数量
//初始化一个[]interface{}类型的变量snapshot来存储m的值中的元素值
snapshot := make([]interface{}, initialLen)
actualLen := 0
//按照既定顺序将迭代值设置到快照值(变量snapshot的值)的指定元素位置上,这一过程并不会创建任何新值。
for key := range set.m {
if actualLen < initialLen {
snapshot[actualLen] = key
} else {//m的值中的元素数量有所增加,使得实际迭代的次数大于先前初始化的快照值的长度
snapshot = append(snapshot, key)//使用append函数向快照值追加元素值。
}
actualLen++//实际迭代的次数
}
//对于已被初始化的[]interface{}类型的切片值来说,未被显示初始化的元素位置上的值均为nil。
//m的值中的元素数量有所减少,使得实际迭代的次数小于先前初始化的快照值的长度。
//这样快照值的尾部存在若干个没有任何意义的值为nil的元素,
//可以通过snapshot = snapshot[:actualLen]将无用的元素值从快照值中去掉。
if actualLen < initialLen {
snapshot = snapshot[:actualLen]
}
return snapshot
}
注意:在 Elements 方法中针对并发访问和修改 m 的值的情况采取了一些措施。但是由于m的值本身并不是并发安全的,所以并不能保证 Elements 方法的执行总会准确无误。要做到真正的并发安全,还需要一些辅助的手段,比如读写互斥量。
(8).获取自身的字符串表示形式。
//这个String方法的签名算是一个惯用法。 //代码包fmt中的打印函数总会使用参数值附带的具有如此签名的String方法的结果值作为该参数值的字符串表示形式。
func (set *HashSet) String() string {
var buf bytes.Buffer//作为结果值的缓冲区
buf.WriteString("HashSet{")
first := true
for key := range set.m {
if first {
first = false
} else {
buf.WriteString(",")
}
buf.WriteString(fmt.Sprintf("%v", key))
}
//n := 1
//for key := range set.m {
// buf.WriteString(fmt.Sprintf("%v", key))
// if n == len(set.m) {//最后一个元素的后面不添加逗号
// break;
// } else {
// buf.WriteString(",")
// }
// n++;
//}
buf.WriteString("}")
return buf.String()
}
如上已经完整地编写了一个具备常用功能的Set的实现类型,后面将讲解更多的高级功能来完善它。
3.高级功能
集合 Set 的真包含的判断功能。根据集合代数中的描述,如果集合 A 真包含了集合 B,那么就可以说集合 A 是集合 B 的一个超集。
// 判断集合 set 是否是集合 other 的超集
func (set *HashSet) IsSuperset(other *HashSet) bool {
if other == nil {//如果other为nil,则other不是set的子集
return false
}
setLen := set.Len()//获取set的元素值数量
otherLen := other.Len()//获取other的元素值数量
if setLen == 0 || setLen == otherLen {//set的元素值数量等于0或者等于other的元素数量
return false
}
if setLen > 0 && otherLen == 0 {//other为元素数量为0,set元素数量大于0,则set也是other的超集
return true
}
for _, v := range other.Elements() {
if !set.Contains(v) {//只要set中有一个包含other中的数据,就返回false
return false
}
}
return true
}









