set.go
// set project set.go package settype Set interface {Add(e interface{}) boolRemove(e interface{})Clear()Contains(e interface{}) boolLen() intSame(other Set) boolElements() []interface{}String() string }// 将集合other添加到集合one中 func AddSet(one Set, other Set) {if one == nil || other == nil || other.Len() == 0 {return}for _, v := range other.Elements() {one.Add(v)} }// 判断集合 one 是否是集合 other 的超集 func IsSuperset(one Set, other Set) bool {if one == nil || other == nil {return false}oneLen := one.Len()otherLen := other.Len()if oneLen == 0 || oneLen <= otherLen {return false}if oneLen > 0 && otherLen == 0 {return true}for _, v := range other.Elements() {if !one.Contains(v) {return false}}return true }// 生成集合 one 和集合 other 的并集 func Union(one Set, other Set) Set {if one == nil && other == nil {return nil}unionedSet := NewSimpleSet()AddSet(unionedSet, one)AddSet(unionedSet, other)return unionedSet }// 生成集合 one 和集合 other 的交集 func Intersect(one Set, other Set) Set {if one == nil || other == nil {return nil}intersectedSet := NewSimpleSet()if one.Len() == 0 || other.Len() == 0 {return intersectedSet}if one.Len() < other.Len() {for _, v := range one.Elements() {if other.Contains(v) {intersectedSet.Add(v)}}} else {for _, v := range other.Elements() {if one.Contains(v) {intersectedSet.Add(v)}}}return intersectedSet }// 生成集合 one 对集合 other 的差集 func Difference(one Set, other Set) Set {if one == nil {return nil}differencedSet := NewSimpleSet()if other == nil || other.Len() == 0 {AddSet(differencedSet, one)return differencedSet}for _, v := range one.Elements() {if !other.Contains(v) {differencedSet.Add(v)}}return differencedSet }// 生成集合 one 和集合 other 的对称差集 func SymmetricDifference(one Set, other Set) Set {diffA := Difference(one, other)if other == nil || other.Len() == 0 {return diffA}diffB := Difference(other, one)return Union(diffA, diffB) }// 返回一个HashSet func NewSimpleSet() Set {return NewHashSet() }// 判断给定value是否为集合 func IsSet(value interface{}) bool {if _, ok := value.(Set); ok {return true}return false }
hash_set.go
// hash_set package setimport ("bytes""fmt" )type HashSet struct {m map[interface{}]bool }// 创建和初始化HashSet的方法 func NewHashSet() *HashSet {return &HashSet{m: make(map[interface{}]bool)} }// 向HashSet中添加元素的方法 func (set *HashSet) Add(e interface{}) bool {if !set.m[e] {set.m[e] = truereturn true}return false }// 删除HashSet中指定的元素 func (set *HashSet) Remove(e interface{}) {delete(set.m, e) }// 清除HashSet中的所有元素 func (set *HashSet) Clear() {set.m = make(map[interface{}]bool) }// 判断HashSet是否包含指定元素 func (set *HashSet) Contains(e interface{}) bool {return set.m[e] }// 获取HashSet中元素值数量 func (set *HashSet) Len() int {return len(set.m) }// 判断两个Set类型值是否相同 func (set *HashSet) Same(other Set) bool {if other == nil {return false}if set.Len() != other.Len() {return false}for key := range set.m {if !other.Contains(key) {return false}}return true }// 生成HashSet的一个快照 func (set *HashSet) Elements() []interface{} {initialLen := len(set.m)snapshot := make([]interface{}, initialLen)actualLen := 0for key := range set.m {if actualLen < initialLen {snapshot[actualLen] = key} else {snapshot = append(snapshot, key)}actualLen++}if actualLen < initialLen {snapshot = snapshot[:actualLen]}return snapshot }// 获取HashSet自身字符串表示形式 func (set *HashSet) String() string {var buf bytes.Bufferbuf.WriteString("Set{")first := truefor key := range set.m {if first {first = false} else {buf.WriteString(" ")}buf.WriteString(fmt.Sprintf("%v", key))}buf.WriteString("}")return buf.String() }
功能测试:
set_test.go
// set_test package setimport ("bytes""fmt""math/rand""runtime/debug""strings""testing""time" )func testSetLenAndContains(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sLenAndContains...", typeName)set, expectedElemMap := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)expectedLen := len(expectedElemMap)if set.Len() != expectedLen {t.Errorf("ERROR: The length of %s value %d is not %d!\n",set.Len(), typeName, expectedLen)t.FailNow()}t.Logf("The length of %s value is %d.\n", typeName, set.Len())for k := range expectedElemMap {if !set.Contains(k) {t.Errorf("ERROR: The %s value %v do not contains %v!",set, typeName, k)t.FailNow()}} }func testSetAdd(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sAdd...", typeName)set := newSet()var randElem interface{}var result boolexpectedElemMap := make(map[interface{}]bool)for i := 0; i < 5; i++ {randElem = genRandElement()t.Logf("Add %v to the %s value %v.\n", randElem, typeName, set)result = set.Add(randElem)if expectedElemMap[randElem] && result {t.Errorf("ERROR: The element adding (%v => %v) is successful but should be failing!\n",randElem, set)t.FailNow()}if !expectedElemMap[randElem] && !result {t.Errorf("ERROR: The element adding (%v => %v) is failing!\n",randElem, set)t.FailNow()}expectedElemMap[randElem] = true}t.Logf("The %s value: %v.", typeName, set)expectedLen := len(expectedElemMap)if set.Len() != expectedLen {t.Errorf("ERROR: The length of %s value %d is not %d!\n",set.Len(), typeName, expectedLen)t.FailNow()}t.Logf("The length of %s value is %d.\n", typeName, set.Len())for k := range expectedElemMap {if !set.Contains(k) {t.Errorf("ERROR: The %s value %v do not contains %v!",set, typeName, k)t.FailNow()}} }func testSetRemove(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sRemove...", typeName)set, expectedElemMap := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)t.Logf("The length of %s value is %d.\n", typeName, set.Len())var number intfor k, _ := range expectedElemMap {if number%2 == 0 {t.Logf("Remove %v from the HashSet value %v.\n", k, set)set.Remove(k)if set.Contains(k) {t.Errorf("ERROR: The element removing (%v => %v) is failing!\n",k, set)t.FailNow()}delete(expectedElemMap, k)}number++}expectedLen := len(expectedElemMap)if set.Len() != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", set.Len(), expectedLen)t.FailNow()}t.Logf("The length of %s value is %d.\n", typeName, set.Len())for _, v := range set.Elements() {if !expectedElemMap[v] {t.Errorf("ERROR: The HashSet value %v contains %v but should not contains!", set, v)t.FailNow()}} }func testSetClear(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sClear...", typeName)set, _ := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)t.Logf("The length of %s value is %d.\n", typeName, set.Len())t.Logf("Clear the HashSet value %v.\n", set)set.Clear()expectedLen := 0if set.Len() != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", set.Len(), expectedLen)t.FailNow()}t.Logf("The length of %s value is %d.\n", typeName, set.Len()) }func testSetElements(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sElements...", typeName)set, expectedElemMap := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)t.Logf("The length of %s value is %d.\n", typeName, set.Len())elems := set.Elements()t.Logf("The elements of %s value is %v.\n", typeName, elems)expectedLen := len(expectedElemMap)if len(elems) != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", len(elems), expectedLen)t.FailNow()}t.Logf("The length of elements is %d.\n", len(elems))for _, v := range elems {if !expectedElemMap[v] {t.Errorf("ERROR: The elements %v contains %v but should not contains!", set, v)t.FailNow()}} }func testSetSame(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sSame...", typeName)set, _ := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)t.Logf("The length of %s value is %d.\n", typeName, set.Len())set2 := newSet()t.Logf("Clone the HashSet value %v...\n", set)for _, v := range set.Elements() {set2.Add(v)}result := set2.Same(set)if !result {t.Errorf("ERROR: Two sets are not same!")}t.Logf("Two sets are same.") }func testSetString(t *testing.T, newSet func() Set, typeName string) {t.Logf("Starting Test%sString...", typeName)set, _ := genRandSet(newSet)t.Logf("Got a %s value: %v.", typeName, set)setStr := set.String()t.Logf("The string of %s value is %s.\n", typeName, setStr)var elemStr stringfor _, v := range set.Elements() {elemStr = fmt.Sprintf("%v", v)if !strings.Contains(setStr, elemStr) {t.Errorf("ERROR: The string of %s value %s do not contains %s!",typeName, setStr, elemStr)t.FailNow()}} }// ----- Set 公用函数测试 ----- func TestIsSuperset(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestIsSuperset...")set, _ := genRandSet(func() Set { return NewSimpleSet() })set2 := NewSimpleSet()for _, v := range set.Elements() {set2.Add(v)}for extraElem := genRandElement(); ; {if set2.Add(extraElem) {break} else {time.Sleep(10 * time.Millisecond)}}if !IsSuperset(set2, set) {t.Errorf("ERROR: The HashSet value %v is not a superset of %v!\n", set2, set)t.FailNow()} else {t.Logf("The HashSet value %v is a superset of %v.\n", set2, set)}for extraElem := genRandElement(); ; {if set.Add(extraElem) {break} else {time.Sleep(10 * time.Millisecond)}}if IsSuperset(set2, set) {t.Errorf("ERROR: The HashSet value %v should not be a superset of %v!\n", set2, set)t.FailNow()} else {t.Logf("The HashSet value %v is not a superset of %v.\n", set2, set)} }func TestUnion(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestUnion...")set, _ := genRandSet(func() Set { return NewSimpleSet() })t.Logf("The set value: %v", set)set2, _ := genRandSet(func() Set { return NewSimpleSet() })uSet := Union(set, set2)t.Logf("The set value (2): %v", set2)for _, v := range set.Elements() {if !uSet.Contains(v) {t.Errorf("ERROR: The union set value %v do not contains %v!",uSet, v)t.FailNow()}}for _, v := range set2.Elements() {if !uSet.Contains(v) {t.Errorf("ERROR: The union set value %v do not contains %v!",uSet, v)t.FailNow()}}t.Logf("The set value %v is a unioned set of %v and %v", uSet, set, set2) }func TestIntersect(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestIntersect...")commonElem := genRandElement()set, _ := genRandSet(func() Set { return NewSimpleSet() })set.Add(commonElem)t.Logf("The set value: %v", set)set2, _ := genRandSet(func() Set { return NewSimpleSet() })set2.Add(commonElem)t.Logf("The set value (2): %v", set2)iSet := Intersect(set, set2)for _, v := range iSet.Elements() {if !set.Contains(v) {t.Errorf("ERROR: The set value %v do not contains %v!",set, v)t.FailNow()}if !set2.Contains(v) {t.Errorf("ERROR: The set value %v do not contains %v!",set2, v)t.FailNow()}}t.Logf("The set value %v is a intersected set of %v and %v", iSet, set, set2) }func TestDifference(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestDifference...")commonElem := genRandElement()set, _ := genRandSet(func() Set { return NewSimpleSet() })set.Add(commonElem)t.Logf("The set value: %v", set)set2, _ := genRandSet(func() Set { return NewSimpleSet() })set2.Add(commonElem)t.Logf("The set value (2): %v", set2)dSet := Difference(set, set2)for _, v := range dSet.Elements() {if !set.Contains(v) {t.Errorf("ERROR: The set value %v do not contains %v!",set, v)t.FailNow()}if set2.Contains(v) {t.Errorf("ERROR: The set value %v contains %v!",set2, v)t.FailNow()}}t.Logf("The set value %v is a differenced set of %v to %v", dSet, set, set2) }func TestSymmetricDifference(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestSymmetricDifference...")commonElem := genRandElement()set, _ := genRandSet(func() Set { return NewSimpleSet() })set.Add(commonElem)t.Logf("The set value: %v", set)set2, _ := genRandSet(func() Set { return NewSimpleSet() })set2.Add(commonElem)t.Logf("The set value (2): %v", set2)sdSet := SymmetricDifference(set, set2)for _, v := range sdSet.Elements() {if set.Contains(v) && set2.Contains(v) {t.Errorf("ERROR: The element %v can not be a common element of %v to %v!",v, set, set2)t.FailNow()}}t.Logf("The set value %v is a symmetric differenced set of %v to %v", sdSet, set, set2) }// ----- 随机测试对象生成函数 ----- func genRandSet(newSet func() Set) (set Set, elemMap map[interface{}]bool) {set = newSet()elemMap = make(map[interface{}]bool)var enough boolfor !enough {e := genRandElement()set.Add(e)elemMap[e] = trueif len(elemMap) >= 3 {enough = true}}return }func genRandElement() interface{} {seed := rand.Int63n(10000)switch seed {case 0:return genRandInt()case 1:return genRandString()case 2:return struct {num int64str string}{genRandInt(), genRandString()}default:const length = 2arr := new([length]interface{})for i := 0; i < length; i++ {if i%2 == 0 {arr[i] = genRandInt()} else {arr[i] = genRandString()}}return *arr} }func genRandString() string {var buff bytes.Buffervar prev stringvar curr stringfor i := 0; buff.Len() < 3; i++ {curr = string(genRandAZAscii())if curr == prev {continue} else {prev = curr}buff.WriteString(curr)}return buff.String() }func genRandAZAscii() int {min := 65 // Amax := 90 // Z rand.Seed(time.Now().UnixNano())return min + rand.Intn(max-min) }func genRandInt() int64 {return rand.Int63n(10000) }
hash_set_test.go
// hash_set_test package setimport ("fmt""runtime/debug""strings""testing" )func TestHashSetCreation(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()t.Log("Starting TestHashSetCreation...")hs := NewHashSet()t.Logf("Create a HashSet value: %v\n", hs)if hs == nil {t.Errorf("The result of func NewHashSet is nil!\n")}isSet := IsSet(hs)if !isSet {t.Errorf("The value of HashSet is not Set!\n")} else {t.Logf("The HashSet value is a Set.\n")} }func TestHashSetLenAndContains(t *testing.T) {testSetLenAndContains(t, func() Set { return NewHashSet() }, "HashSet") }func TestHashSetAdd(t *testing.T) {testSetAdd(t, func() Set { return NewHashSet() }, "HashSet") }func TestHashSetRemove(t *testing.T) {testSetRemove(t, func() Set { return NewHashSet() }, "HashSet") }func TestHashSetClear(t *testing.T) {testSetClear(t, func() Set { return NewHashSet() }, "HashSet") }func TestHashSetElements(t *testing.T) {testSetElements(t, func() Set { return NewHashSet() }, "HashSet") }func TestHashSetSame(t *testing.T) {testSetSame(t, func() Set { return NewHashSet() }, "HashSet") }func TestSetString(t *testing.T) {testSetString(t, func() Set { return NewHashSet() }, "HashSet") }func testSetOp(t *testing.T) {defer func() {if err := recover(); err != nil {debug.PrintStack()t.Errorf("Fatal Error: %s\n", err)}}()fmt.Println(222)t.Logf("Starting TestHashSetOp...")hs := NewHashSet()if hs.Len() != 0 {t.Errorf("ERROR: The length of original HashSet value is not 0!\n")t.FailNow()}randElem := genRandElement()expectedElemMap := make(map[interface{}]bool)t.Logf("Add %v to the HashSet value %v.\n", randElem, hs)hs.Add(randElem)expectedElemMap[randElem] = trueexpectedLen := len(expectedElemMap)if hs.Len() != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", hs.Len(), expectedLen)t.FailNow()}var result boolfor i := 0; i < 8; i++ {randElem = genRandElement()t.Logf("Add %v to the HashSet value %v.\n", randElem, hs)result = hs.Add(randElem)if expectedElemMap[randElem] && result {t.Errorf("ERROR: The element adding (%v => %v) is successful but should be failing!\n",randElem, hs)t.FailNow()}if !expectedElemMap[randElem] && !result {t.Errorf("ERROR: The element adding (%v => %v) is failing!\n",randElem, hs)t.FailNow()}expectedElemMap[randElem] = true}expectedLen = len(expectedElemMap)if hs.Len() != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", hs.Len(), expectedLen)t.FailNow()}for k, _ := range expectedElemMap {if !hs.Contains(k) {t.Errorf("ERROR: The HashSet value %v do not contains %v!", hs, k)t.FailNow()}}number := 2for k, _ := range expectedElemMap {if number%2 == 0 {t.Logf("Remove %v from the HashSet value %v.\n", k, hs)hs.Remove(k)if hs.Contains(k) {t.Errorf("ERROR: The element adding (%v => %v) is failing!\n",randElem, hs)t.FailNow()}delete(expectedElemMap, k)}number++}expectedLen = len(expectedElemMap)if hs.Len() != expectedLen {t.Errorf("ERROR: The length of HashSet value %d is not %d!\n", hs.Len(), expectedLen)t.FailNow()}for _, v := range hs.Elements() {if !expectedElemMap[v] {t.Errorf("ERROR: The HashSet value %v contains %v!", hs, v)t.FailNow()}}hs2 := NewHashSet()for k, _ := range expectedElemMap {hs2.Add(k)}if !hs.Same(hs2) {t.Errorf("ERROR: HashSet value %v do not same %v!\n", hs, hs2)t.FailNow()}str := hs.String()t.Logf("The string of HashSet value %v is '%s'.\n", hs, str)for _, v := range hs.Elements() {if !strings.Contains(str, fmt.Sprintf("%v", v)) {t.Errorf("ERROR: '%s' do not contains '%v'!", str, v)t.FailNow()}} }