Removing all temp *Generic based names by swapping with the original names to minimize changes

This commit is contained in:
Ralph Caraveo 2021-12-22 17:56:10 -08:00
parent cd0ae61739
commit 1658d57751
13 changed files with 582 additions and 1579 deletions

View File

@ -46,7 +46,7 @@ func toInterfaces(i []int) []interface{} {
return ifs
}
func benchAdd(b *testing.B, s SetGeneric[int]) {
func benchAdd(b *testing.B, s Set[int]) {
nums := nrand(b.N)
b.ResetTimer()
for _, v := range nums {
@ -55,14 +55,14 @@ func benchAdd(b *testing.B, s SetGeneric[int]) {
}
func BenchmarkAddSafe(b *testing.B) {
benchAdd(b, NewSetGeneric[int]())
benchAdd(b, NewSet[int]())
}
func BenchmarkAddUnsafe(b *testing.B) {
benchAdd(b, NewThreadUnsafeSetGeneric[int]())
benchAdd(b, NewThreadUnsafeSet[int]())
}
func benchRemove(b *testing.B, s SetGeneric[int]) {
func benchRemove(b *testing.B, s Set[int]) {
nums := nrand(b.N)
for _, v := range nums {
s.Add(v)
@ -75,28 +75,28 @@ func benchRemove(b *testing.B, s SetGeneric[int]) {
}
func BenchmarkRemoveSafe(b *testing.B) {
benchRemove(b, NewSetGeneric[int]())
benchRemove(b, NewSet[int]())
}
func BenchmarkRemoveUnsafe(b *testing.B) {
benchRemove(b, NewThreadUnsafeSetGeneric[int]())
benchRemove(b, NewThreadUnsafeSet[int]())
}
func benchCardinality(b *testing.B, s SetGeneric[int]) {
func benchCardinality(b *testing.B, s Set[int]) {
for i := 0; i < b.N; i++ {
s.Cardinality()
}
}
func BenchmarkCardinalitySafe(b *testing.B) {
benchCardinality(b, NewSetGeneric[int]())
benchCardinality(b, NewSet[int]())
}
func BenchmarkCardinalityUnsafe(b *testing.B) {
benchCardinality(b, NewThreadUnsafeSetGeneric[int]())
benchCardinality(b, NewThreadUnsafeSet[int]())
}
func benchClear(b *testing.B, s SetGeneric[int]) {
func benchClear(b *testing.B, s Set[int]) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
s.Clear()
@ -104,14 +104,14 @@ func benchClear(b *testing.B, s SetGeneric[int]) {
}
func BenchmarkClearSafe(b *testing.B) {
benchClear(b, NewSetGeneric[int]())
benchClear(b, NewSet[int]())
}
func BenchmarkClearUnsafe(b *testing.B) {
benchClear(b, NewThreadUnsafeSetGeneric[int]())
benchClear(b, NewThreadUnsafeSet[int]())
}
func benchClone(b *testing.B, n int, s SetGeneric[int]) {
func benchClone(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -124,30 +124,30 @@ func benchClone(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkClone1Safe(b *testing.B) {
benchClone(b, 1, NewSetGeneric[int]())
benchClone(b, 1, NewSet[int]())
}
func BenchmarkClone1Unsafe(b *testing.B) {
benchClone(b, 1, NewThreadUnsafeSetGeneric[int]())
benchClone(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkClone10Safe(b *testing.B) {
benchClone(b, 10, NewSetGeneric[int]())
benchClone(b, 10, NewSet[int]())
}
func BenchmarkClone10Unsafe(b *testing.B) {
benchClone(b, 10, NewThreadUnsafeSetGeneric[int]())
benchClone(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkClone100Safe(b *testing.B) {
benchClone(b, 100, NewSetGeneric[int]())
benchClone(b, 100, NewSet[int]())
}
func BenchmarkClone100Unsafe(b *testing.B) {
benchClone(b, 100, NewThreadUnsafeSetGeneric[int]())
benchClone(b, 100, NewThreadUnsafeSet[int]())
}
func benchContains(b *testing.B, n int, s SetGeneric[int]) {
func benchContains(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -162,30 +162,30 @@ func benchContains(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkContains1Safe(b *testing.B) {
benchContains(b, 1, NewSetGeneric[int]())
benchContains(b, 1, NewSet[int]())
}
func BenchmarkContains1Unsafe(b *testing.B) {
benchContains(b, 1, NewThreadUnsafeSetGeneric[int]())
benchContains(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkContains10Safe(b *testing.B) {
benchContains(b, 10, NewSetGeneric[int]())
benchContains(b, 10, NewSet[int]())
}
func BenchmarkContains10Unsafe(b *testing.B) {
benchContains(b, 10, NewThreadUnsafeSetGeneric[int]())
benchContains(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkContains100Safe(b *testing.B) {
benchContains(b, 100, NewSetGeneric[int]())
benchContains(b, 100, NewSet[int]())
}
func BenchmarkContains100Unsafe(b *testing.B) {
benchContains(b, 100, NewThreadUnsafeSetGeneric[int]())
benchContains(b, 100, NewThreadUnsafeSet[int]())
}
func benchEqual(b *testing.B, n int, s, t SetGeneric[int]) {
func benchEqual(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -199,30 +199,30 @@ func benchEqual(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkEqual1Safe(b *testing.B) {
benchEqual(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchEqual(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkEqual1Unsafe(b *testing.B) {
benchEqual(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchEqual(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkEqual10Safe(b *testing.B) {
benchEqual(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchEqual(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkEqual10Unsafe(b *testing.B) {
benchEqual(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchEqual(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkEqual100Safe(b *testing.B) {
benchEqual(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchEqual(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkEqual100Unsafe(b *testing.B) {
benchEqual(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchEqual(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchDifference(b *testing.B, n int, s, t SetGeneric[int]) {
func benchDifference(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -237,7 +237,7 @@ func benchDifference(b *testing.B, n int, s, t SetGeneric[int]) {
}
}
func benchIsSubset(b *testing.B, n int, s, t SetGeneric[int]) {
func benchIsSubset(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -251,30 +251,30 @@ func benchIsSubset(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkIsSubset1Safe(b *testing.B) {
benchIsSubset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSubset(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSubset1Unsafe(b *testing.B) {
benchIsSubset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsSubset10Safe(b *testing.B) {
benchIsSubset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSubset(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSubset10Unsafe(b *testing.B) {
benchIsSubset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsSubset100Safe(b *testing.B) {
benchIsSubset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSubset(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSubset100Unsafe(b *testing.B) {
benchIsSubset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchIsSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
func benchIsSuperset(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -288,30 +288,30 @@ func benchIsSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkIsSuperset1Safe(b *testing.B) {
benchIsSuperset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSuperset(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSuperset1Unsafe(b *testing.B) {
benchIsSuperset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsSuperset10Safe(b *testing.B) {
benchIsSuperset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSuperset(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSuperset10Unsafe(b *testing.B) {
benchIsSuperset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsSuperset100Safe(b *testing.B) {
benchIsSuperset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsSuperset(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkIsSuperset100Unsafe(b *testing.B) {
benchIsSuperset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchIsProperSubset(b *testing.B, n int, s, t SetGeneric[int]) {
func benchIsProperSubset(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -325,30 +325,30 @@ func benchIsProperSubset(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkIsProperSubset1Safe(b *testing.B) {
benchIsProperSubset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSubset(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSubset1Unsafe(b *testing.B) {
benchIsProperSubset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSubset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsProperSubset10Safe(b *testing.B) {
benchIsProperSubset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSubset(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSubset10Unsafe(b *testing.B) {
benchIsProperSubset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSubset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsProperSubset100Safe(b *testing.B) {
benchIsProperSubset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSubset(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSubset100Unsafe(b *testing.B) {
benchIsProperSubset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSubset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchIsProperSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
func benchIsProperSuperset(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -362,54 +362,54 @@ func benchIsProperSuperset(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkIsProperSuperset1Safe(b *testing.B) {
benchIsProperSuperset(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSuperset(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSuperset1Unsafe(b *testing.B) {
benchIsProperSuperset(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSuperset(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsProperSuperset10Safe(b *testing.B) {
benchIsProperSuperset(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSuperset(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSuperset10Unsafe(b *testing.B) {
benchIsProperSuperset(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSuperset(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIsProperSuperset100Safe(b *testing.B) {
benchIsProperSuperset(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchIsProperSuperset(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkIsProperSuperset100Unsafe(b *testing.B) {
benchIsProperSuperset(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIsProperSuperset(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkDifference1Safe(b *testing.B) {
benchDifference(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchDifference(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkDifference1Unsafe(b *testing.B) {
benchDifference(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkDifference10Safe(b *testing.B) {
benchDifference(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchDifference(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkDifference10Unsafe(b *testing.B) {
benchDifference(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkDifference100Safe(b *testing.B) {
benchDifference(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchDifference(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkDifference100Unsafe(b *testing.B) {
benchDifference(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchIntersect(b *testing.B, n int, s, t SetGeneric[int]) {
func benchIntersect(b *testing.B, n int, s, t Set[int]) {
nums := nrand(int(float64(n) * float64(1.5)))
for _, v := range nums[:n] {
s.Add(v)
@ -425,30 +425,30 @@ func benchIntersect(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkIntersect1Safe(b *testing.B) {
benchIntersect(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchIntersect(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkIntersect1Unsafe(b *testing.B) {
benchIntersect(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIntersect(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIntersect10Safe(b *testing.B) {
benchIntersect(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchIntersect(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkIntersect10Unsafe(b *testing.B) {
benchIntersect(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIntersect(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkIntersect100Safe(b *testing.B) {
benchIntersect(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchIntersect(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkIntersect100Unsafe(b *testing.B) {
benchIntersect(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchIntersect(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchSymmetricDifference(b *testing.B, n int, s, t SetGeneric[int]) {
func benchSymmetricDifference(b *testing.B, n int, s, t Set[int]) {
nums := nrand(int(float64(n) * float64(1.5)))
for _, v := range nums[:n] {
s.Add(v)
@ -464,30 +464,30 @@ func benchSymmetricDifference(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkSymmetricDifference1Safe(b *testing.B) {
benchSymmetricDifference(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchSymmetricDifference(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkSymmetricDifference1Unsafe(b *testing.B) {
benchSymmetricDifference(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchSymmetricDifference(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkSymmetricDifference10Safe(b *testing.B) {
benchSymmetricDifference(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchSymmetricDifference(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkSymmetricDifference10Unsafe(b *testing.B) {
benchSymmetricDifference(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchSymmetricDifference(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkSymmetricDifference100Safe(b *testing.B) {
benchSymmetricDifference(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchSymmetricDifference(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkSymmetricDifference100Unsafe(b *testing.B) {
benchSymmetricDifference(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchSymmetricDifference(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchUnion(b *testing.B, n int, s, t SetGeneric[int]) {
func benchUnion(b *testing.B, n int, s, t Set[int]) {
nums := nrand(n)
for _, v := range nums[:n/2] {
s.Add(v)
@ -503,30 +503,30 @@ func benchUnion(b *testing.B, n int, s, t SetGeneric[int]) {
}
func BenchmarkUnion1Safe(b *testing.B) {
benchUnion(b, 1, NewSetGeneric[int](), NewSetGeneric[int]())
benchUnion(b, 1, NewSet[int](), NewSet[int]())
}
func BenchmarkUnion1Unsafe(b *testing.B) {
benchUnion(b, 1, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchUnion(b, 1, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkUnion10Safe(b *testing.B) {
benchUnion(b, 10, NewSetGeneric[int](), NewSetGeneric[int]())
benchUnion(b, 10, NewSet[int](), NewSet[int]())
}
func BenchmarkUnion10Unsafe(b *testing.B) {
benchUnion(b, 10, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchUnion(b, 10, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func BenchmarkUnion100Safe(b *testing.B) {
benchUnion(b, 100, NewSetGeneric[int](), NewSetGeneric[int]())
benchUnion(b, 100, NewSet[int](), NewSet[int]())
}
func BenchmarkUnion100Unsafe(b *testing.B) {
benchUnion(b, 100, NewThreadUnsafeSetGeneric[int](), NewThreadUnsafeSetGeneric[int]())
benchUnion(b, 100, NewThreadUnsafeSet[int](), NewThreadUnsafeSet[int]())
}
func benchEach(b *testing.B, n int, s SetGeneric[int]) {
func benchEach(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -541,30 +541,30 @@ func benchEach(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkEach1Safe(b *testing.B) {
benchEach(b, 1, NewSetGeneric[int]())
benchEach(b, 1, NewSet[int]())
}
func BenchmarkEach1Unsafe(b *testing.B) {
benchEach(b, 1, NewThreadUnsafeSetGeneric[int]())
benchEach(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkEach10Safe(b *testing.B) {
benchEach(b, 10, NewSetGeneric[int]())
benchEach(b, 10, NewSet[int]())
}
func BenchmarkEach10Unsafe(b *testing.B) {
benchEach(b, 10, NewThreadUnsafeSetGeneric[int]())
benchEach(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkEach100Safe(b *testing.B) {
benchEach(b, 100, NewSetGeneric[int]())
benchEach(b, 100, NewSet[int]())
}
func BenchmarkEach100Unsafe(b *testing.B) {
benchEach(b, 100, NewThreadUnsafeSetGeneric[int]())
benchEach(b, 100, NewThreadUnsafeSet[int]())
}
func benchIter(b *testing.B, n int, s SetGeneric[int]) {
func benchIter(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -580,30 +580,30 @@ func benchIter(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkIter1Safe(b *testing.B) {
benchIter(b, 1, NewSetGeneric[int]())
benchIter(b, 1, NewSet[int]())
}
func BenchmarkIter1Unsafe(b *testing.B) {
benchIter(b, 1, NewThreadUnsafeSetGeneric[int]())
benchIter(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkIter10Safe(b *testing.B) {
benchIter(b, 10, NewSetGeneric[int]())
benchIter(b, 10, NewSet[int]())
}
func BenchmarkIter10Unsafe(b *testing.B) {
benchIter(b, 10, NewThreadUnsafeSetGeneric[int]())
benchIter(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkIter100Safe(b *testing.B) {
benchIter(b, 100, NewSetGeneric[int]())
benchIter(b, 100, NewSet[int]())
}
func BenchmarkIter100Unsafe(b *testing.B) {
benchIter(b, 100, NewThreadUnsafeSetGeneric[int]())
benchIter(b, 100, NewThreadUnsafeSet[int]())
}
func benchIterator(b *testing.B, n int, s SetGeneric[int]) {
func benchIterator(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -619,30 +619,30 @@ func benchIterator(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkIterator1Safe(b *testing.B) {
benchIterator(b, 1, NewSetGeneric[int]())
benchIterator(b, 1, NewSet[int]())
}
func BenchmarkIterator1Unsafe(b *testing.B) {
benchIterator(b, 1, NewThreadUnsafeSetGeneric[int]())
benchIterator(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkIterator10Safe(b *testing.B) {
benchIterator(b, 10, NewSetGeneric[int]())
benchIterator(b, 10, NewSet[int]())
}
func BenchmarkIterator10Unsafe(b *testing.B) {
benchIterator(b, 10, NewThreadUnsafeSetGeneric[int]())
benchIterator(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkIterator100Safe(b *testing.B) {
benchIterator(b, 100, NewSetGeneric[int]())
benchIterator(b, 100, NewSet[int]())
}
func BenchmarkIterator100Unsafe(b *testing.B) {
benchIterator(b, 100, NewThreadUnsafeSetGeneric[int]())
benchIterator(b, 100, NewThreadUnsafeSet[int]())
}
func benchString(b *testing.B, n int, s SetGeneric[int]) {
func benchString(b *testing.B, n int, s Set[int]) {
nums := nrand(n)
for _, v := range nums {
s.Add(v)
@ -655,30 +655,30 @@ func benchString(b *testing.B, n int, s SetGeneric[int]) {
}
func BenchmarkString1Safe(b *testing.B) {
benchString(b, 1, NewSetGeneric[int]())
benchString(b, 1, NewSet[int]())
}
func BenchmarkString1Unsafe(b *testing.B) {
benchString(b, 1, NewThreadUnsafeSetGeneric[int]())
benchString(b, 1, NewThreadUnsafeSet[int]())
}
func BenchmarkString10Safe(b *testing.B) {
benchString(b, 10, NewSetGeneric[int]())
benchString(b, 10, NewSet[int]())
}
func BenchmarkString10Unsafe(b *testing.B) {
benchString(b, 10, NewThreadUnsafeSetGeneric[int]())
benchString(b, 10, NewThreadUnsafeSet[int]())
}
func BenchmarkString100Safe(b *testing.B) {
benchString(b, 100, NewSetGeneric[int]())
benchString(b, 100, NewSet[int]())
}
func BenchmarkString100Unsafe(b *testing.B) {
benchString(b, 100, NewThreadUnsafeSetGeneric[int]())
benchString(b, 100, NewThreadUnsafeSet[int]())
}
func benchToSlice(b *testing.B, s SetGeneric[int]) {
func benchToSlice(b *testing.B, s Set[int]) {
nums := nrand(b.N)
for _, v := range nums {
s.Add(v)
@ -691,9 +691,9 @@ func benchToSlice(b *testing.B, s SetGeneric[int]) {
}
func BenchmarkToSliceSafe(b *testing.B) {
benchToSlice(b, NewSetGeneric[int]())
benchToSlice(b, NewSet[int]())
}
func BenchmarkToSliceUnsafe(b *testing.B) {
benchToSlice(b, NewThreadUnsafeSetGeneric[int]())
benchToSlice(b, NewThreadUnsafeSet[int]())
}

View File

@ -27,13 +27,13 @@ package mapset
// Iterator defines an iterator over a Set, its C channel can be used to range over the Set's
// elements.
type Iterator struct {
C <-chan interface{}
type Iterator[T comparable] struct {
C <-chan T
stop chan struct{}
}
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
func (i *Iterator) Stop() {
func (i *Iterator[T]) Stop() {
// Allows for Stop() to be called multiple times
// (close() panics when called on already closed channel)
defer func() {
@ -48,10 +48,10 @@ func (i *Iterator) Stop() {
}
// newIterator returns a new Iterator instance together with its item and stop channels.
func newIterator() (*Iterator, chan<- interface{}, <-chan struct{}) {
itemChan := make(chan interface{})
func newIterator[T comparable]() (*Iterator[T], chan<- T, <-chan struct{}) {
itemChan := make(chan T)
stopChan := make(chan struct{})
return &Iterator{
return &Iterator[T]{
C: itemChan,
stop: stopChan,
}, itemChan, stopChan

View File

@ -35,7 +35,7 @@ type yourType struct {
func Test_ExampleIterator(t *testing.T) {
s := NewSetFromSliceGeneric[*yourType]([]*yourType{
s := NewSetFromSlice[*yourType]([]*yourType{
&yourType{name: "Alise"},
&yourType{name: "Bob"},
&yourType{name: "John"},

View File

@ -1,58 +0,0 @@
/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package mapset
// IteratorGeneric defines an iterator over a Set, its C channel can be used to range over the Set's
// elements.
type IteratorGeneric[T comparable] struct {
C <-chan T
stop chan struct{}
}
// Stop stops the Iterator, no further elements will be received on C, C will be closed.
func (i *IteratorGeneric[T]) Stop() {
// Allows for Stop() to be called multiple times
// (close() panics when called on already closed channel)
defer func() {
recover()
}()
close(i.stop)
// Exhaust any remaining elements.
for range i.C {
}
}
// newIterator returns a new Iterator instance together with its item and stop channels.
func newIteratorGeneric[T comparable]() (*IteratorGeneric[T], chan<- T, <-chan struct{}) {
itemChan := make(chan T)
stopChan := make(chan struct{})
return &IteratorGeneric[T]{
C: itemChan,
stop: stopChan,
}, itemChan, stopChan
}

89
set.go
View File

@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Package mapset implements a simple and generic set collection.
// Package mapset implements a simple and set collection.
// Items stored within it are unordered and unique. It supports
// typical set operations: membership testing, intersection, union,
// difference, symmetric difference and cloning.
@ -38,10 +38,10 @@ package mapset
// Set is the primary interface provided by the mapset package. It
// represents an unordered set of data and a large number of
// operations that can be applied to that set.
type Set interface {
type Set[T comparable] interface {
// Adds an element to the set. Returns whether
// the item was added.
Add(i interface{}) bool
Add(val T) bool
// Returns the number of elements in the set.
Cardinality() int
@ -52,11 +52,11 @@ type Set interface {
// Returns a clone of the set using the same
// implementation, duplicating all keys.
Clone() Set
Clone() Set[T]
// Returns whether the given items
// are all in the set.
Contains(i ...interface{}) bool
Contains(val ...T) bool
// Returns the difference between this set
// and other. The returned set will contain
@ -67,7 +67,7 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, Difference will
// panic.
Difference(other Set) Set
Difference(other Set[T]) Set[T]
// Determines if two sets are equal to each
// other. If they have the same cardinality
@ -78,7 +78,7 @@ type Set interface {
// Note that the argument to Equal must be
// of the same type as the receiver of the
// method. Otherwise, Equal will panic.
Equal(other Set) bool
Equal(other Set[T]) bool
// Returns a new set containing only the elements
// that exist only in both sets.
@ -87,7 +87,7 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, Intersect will
// panic.
Intersect(other Set) Set
Intersect(other Set[T]) Set[T]
// Determines if every element in this set is in
// the other set but the two sets are not equal.
@ -96,7 +96,7 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, IsProperSubset
// will panic.
IsProperSubset(other Set) bool
IsProperSubset(other Set[T]) bool
// Determines if every element in the other set
// is in this set but the two sets are not
@ -106,7 +106,7 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, IsSuperset will
// panic.
IsProperSuperset(other Set) bool
IsProperSuperset(other Set[T]) bool
// Determines if every element in this set is in
// the other set.
@ -115,7 +115,7 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, IsSubset will
// panic.
IsSubset(other Set) bool
IsSubset(other Set[T]) bool
// Determines if every element in the other set
// is in this set.
@ -124,22 +124,22 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, IsSuperset will
// panic.
IsSuperset(other Set) bool
IsSuperset(other Set[T]) bool
// Iterates over elements and executes the passed func against each element.
// If passed func returns true, stop iteration at the time.
Each(func(interface{}) bool)
Each(func(T) bool)
// Returns a channel of elements that you can
// range over.
Iter() <-chan interface{}
Iter() <-chan T
// Returns an Iterator object that you can
// use to range over the set.
Iterator() *Iterator
Iterator() *Iterator[T]
// Remove a single element from the set.
Remove(i interface{})
Remove(i T)
// Provides a convenient string representation
// of the current state of the set.
@ -152,66 +152,73 @@ type Set interface {
// must be of the same type as the receiver
// of the method. Otherwise, SymmetricDifference
// will panic.
SymmetricDifference(other Set) Set
SymmetricDifference(other Set[T]) Set[T]
// Returns a new set with all elements in both sets.
//
// Note that the argument to Union must be of the
// same type as the receiver of the method.
// Otherwise, IsSuperset will panic.
Union(other Set) Set
Union(other Set[T]) Set[T]
// Pop removes and returns an arbitrary item from the set.
Pop() interface{}
Pop() any
// Returns all subsets of a given set (Power Set).
PowerSet() Set
// PowerSet({x, y, z}) -> {{}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z}}
PowerSet() Set[any]
// Returns the Cartesian Product of two sets.
CartesianProduct(other Set) Set
CartesianProduct(other Set[T]) Set[any]
// Returns the members of the set as a slice.
ToSlice() []interface{}
ToSlice() []T
// MarshalJSON will marshal the set into a JSON-based representation.
MarshalJSON() ([]byte, error)
// UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure.
// For this to work, set subtypes must implemented the Marshal/Unmarshal interface.
UnmarshalJSON(b []byte) error
}
// NewSet creates and returns a reference to an empty set. Operations
// on the resulting set are thread-safe.
func NewSet(s ...interface{}) Set {
set := newThreadSafeSet()
for _, item := range s {
set.Add(item)
func NewSet[T comparable](vals ...T) Set[T] {
s := newThreadSafeSet[T]()
for _, item := range vals {
s.Add(item)
}
return &set
return &s
}
// NewSetWith creates and returns a new set with the given elements.
// Operations on the resulting set are thread-safe.
func NewSetWith(elts ...interface{}) Set {
return NewSetFromSlice(elts)
func NewSetWith[T comparable](vals ...T) Set[T] {
return NewSetFromSlice[T](vals)
}
// NewSetFromSlice creates and returns a reference to a set from an
// existing slice. Operations on the resulting set are thread-safe.
func NewSetFromSlice(s []interface{}) Set {
a := NewSet(s...)
return a
func NewSetFromSlice[T comparable](v []T) Set[T] {
s := NewSet(v...)
return s
}
// NewThreadUnsafeSet creates and returns a reference to an empty set.
// Operations on the resulting set are not thread-safe.
func NewThreadUnsafeSet() Set {
set := newThreadUnsafeSet()
return &set
func NewThreadUnsafeSet[T comparable]() Set[T] {
s := newThreadUnsafeSet[T]()
return &s
}
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
// set from an existing slice. Operations on the resulting set are
// not thread-safe.
func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
a := NewThreadUnsafeSet()
for _, item := range s {
a.Add(item)
func NewThreadUnsafeSetFromSlice[T comparable](v []T) Set[T] {
s := NewThreadUnsafeSet[T]()
for _, item := range v {
s.Add(item)
}
return a
return s
}

View File

@ -1,229 +0,0 @@
/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
// Package mapset implements a simple and generic set collection.
// Items stored within it are unordered and unique. It supports
// typical set operations: membership testing, intersection, union,
// difference, symmetric difference and cloning.
//
// Package mapset provides two implementations of the Set
// interface. The default implementation is safe for concurrent
// access, but a non-thread-safe implementation is also provided for
// programs that can benefit from the slight speed improvement and
// that can enforce mutual exclusion through other means.
package mapset
// TODO: delete this...just messing with generics.
// func Equal[T comparable](a, b T) bool {
// return a == b
// }
// Set is the primary interface provided by the mapset package. It
// represents an unordered set of data and a large number of
// operations that can be applied to that set.
type SetGeneric[T comparable] interface {
// Adds an element to the set. Returns whether
// the item was added.
Add(val T) bool
// Returns the number of elements in the set.
Cardinality() int
// Removes all elements from the set, leaving
// the empty set.
Clear()
// Returns a clone of the set using the same
// implementation, duplicating all keys.
Clone() SetGeneric[T]
// Returns whether the given items
// are all in the set.
Contains(val ...T) bool
// Returns the difference between this set
// and other. The returned set will contain
// all elements of this set that are not also
// elements of other.
//
// Note that the argument to Difference
// must be of the same type as the receiver
// of the method. Otherwise, Difference will
// panic.
Difference(other SetGeneric[T]) SetGeneric[T]
// Determines if two sets are equal to each
// other. If they have the same cardinality
// and contain the same elements, they are
// considered equal. The order in which
// the elements were added is irrelevant.
//
// Note that the argument to Equal must be
// of the same type as the receiver of the
// method. Otherwise, Equal will panic.
Equal(other SetGeneric[T]) bool
// Returns a new set containing only the elements
// that exist only in both sets.
//
// Note that the argument to Intersect
// must be of the same type as the receiver
// of the method. Otherwise, Intersect will
// panic.
Intersect(other SetGeneric[T]) SetGeneric[T]
// Determines if every element in this set is in
// the other set but the two sets are not equal.
//
// Note that the argument to IsProperSubset
// must be of the same type as the receiver
// of the method. Otherwise, IsProperSubset
// will panic.
IsProperSubset(other SetGeneric[T]) bool
// Determines if every element in the other set
// is in this set but the two sets are not
// equal.
//
// Note that the argument to IsSuperset
// must be of the same type as the receiver
// of the method. Otherwise, IsSuperset will
// panic.
IsProperSuperset(other SetGeneric[T]) bool
// Determines if every element in this set is in
// the other set.
//
// Note that the argument to IsSubset
// must be of the same type as the receiver
// of the method. Otherwise, IsSubset will
// panic.
IsSubset(other SetGeneric[T]) bool
// Determines if every element in the other set
// is in this set.
//
// Note that the argument to IsSuperset
// must be of the same type as the receiver
// of the method. Otherwise, IsSuperset will
// panic.
IsSuperset(other SetGeneric[T]) bool
// Iterates over elements and executes the passed func against each element.
// If passed func returns true, stop iteration at the time.
Each(func(T) bool)
// Returns a channel of elements that you can
// range over.
Iter() <-chan T
// Returns an Iterator object that you can
// use to range over the set.
Iterator() *IteratorGeneric[T]
// Remove a single element from the set.
Remove(i T)
// Provides a convenient string representation
// of the current state of the set.
String() string
// Returns a new set with all elements which are
// in either this set or the other set but not in both.
//
// Note that the argument to SymmetricDifference
// must be of the same type as the receiver
// of the method. Otherwise, SymmetricDifference
// will panic.
SymmetricDifference(other SetGeneric[T]) SetGeneric[T]
// Returns a new set with all elements in both sets.
//
// Note that the argument to Union must be of the
// same type as the receiver of the method.
// Otherwise, IsSuperset will panic.
Union(other SetGeneric[T]) SetGeneric[T]
// Pop removes and returns an arbitrary item from the set.
Pop() any
// Returns all subsets of a given set (Power Set).
// PowerSet({x, y, z}) -> {{}, {x}, {y}, {z}, {x, y}, {x, z}, {y, z}, {x, y, z}}
PowerSet() SetGeneric[any]
// Returns the Cartesian Product of two sets.
CartesianProduct(other SetGeneric[T]) SetGeneric[any]
// Returns the members of the set as a slice.
ToSlice() []T
// MarshalJSON will marshal the set into a JSON-based representation.
MarshalJSON() ([]byte, error)
// UnmarshalJSON will unmarshal a JSON-based byte slice into a full Set datastructure.
// For this to work, set subtypes must implemented the Marshal/Unmarshal interface.
UnmarshalJSON(b []byte) error
}
// NewSet creates and returns a reference to an empty set. Operations
// on the resulting set are thread-safe.
func NewSetGeneric[T comparable](vals ...T) SetGeneric[T] {
s := newThreadSafeSetGeneric[T]()
for _, item := range vals {
s.Add(item)
}
return &s
}
// NewSetWith creates and returns a new set with the given elements.
// Operations on the resulting set are thread-safe.
func NewSetWithGeneric[T comparable](vals ...T) SetGeneric[T] {
return NewSetFromSliceGeneric[T](vals)
}
// NewSetFromSlice creates and returns a reference to a set from an
// existing slice. Operations on the resulting set are thread-safe.
func NewSetFromSliceGeneric[T comparable](v []T) SetGeneric[T] {
s := NewSetGeneric(v...)
return s
}
// NewThreadUnsafeSetGeneric creates and returns a reference to an empty set.
// Operations on the resulting set are not thread-safe.
func NewThreadUnsafeSetGeneric[T comparable]() SetGeneric[T] {
s := newThreadUnsafeSetGeneric[T]()
return &s
}
// NewThreadUnsafeSetFromSlice creates and returns a reference to a
// set from an existing slice. Operations on the resulting set are
// not thread-safe.
func NewThreadUnsafeSetFromSliceGeneric[T comparable](v []T) SetGeneric[T] {
s := NewThreadUnsafeSetGeneric[T]()
for _, item := range v {
s.Add(item)
}
return s
}

View File

@ -27,65 +27,43 @@ package mapset
import "testing"
func makeSet(ints []int) Set {
set := NewSet()
for _, i := range ints {
set.Add(i)
}
return set
}
func makeSetInt(ints []int) SetGeneric[int] {
s := NewSetGeneric[int]()
func makeSetInt(ints []int) Set[int] {
s := NewSet[int]()
for _, i := range ints {
s.Add(i)
}
return s
}
func makeUnsafeSet(ints []int) Set {
set := NewThreadUnsafeSet()
for _, i := range ints {
set.Add(i)
}
return set
}
func makeUnsafeSetInt(ints []int) SetGeneric[int] {
s := NewThreadUnsafeSetGeneric[int]()
func makeUnsafeSetInt(ints []int) Set[int] {
s := NewThreadUnsafeSet[int]()
for _, i := range ints {
s.Add(i)
}
return s
}
func assertEqual(a, b Set, t *testing.T) {
if !a.Equal(b) {
t.Errorf("%v != %v\n", a, b)
}
}
func assertEqualGeneric[T comparable](a, b SetGeneric[T], t *testing.T) {
func assertEqual[T comparable](a, b Set[T], t *testing.T) {
if !a.Equal(b) {
t.Errorf("%v != %v\n", a, b)
}
}
func Test_NewSet(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
if a.Cardinality() != 0 {
t.Error("NewSet should start out as an empty set")
}
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{}), NewSetGeneric[int](), t)
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{1}), NewSetGeneric[int](1), t)
assertEqualGeneric(NewSetFromSliceGeneric[int]([]int{1, 2}), NewSetGeneric[int](1, 2), t)
assertEqualGeneric(NewSetFromSliceGeneric[string]([]string{"a"}), NewSetGeneric[string]("a"), t)
assertEqualGeneric(NewSetFromSliceGeneric[string]([]string{"a", "b"}), NewSetGeneric[string]("a", "b"), t)
assertEqual(NewSetFromSlice[int]([]int{}), NewSet[int](), t)
assertEqual(NewSetFromSlice[int]([]int{1}), NewSet[int](1), t)
assertEqual(NewSetFromSlice[int]([]int{1, 2}), NewSet[int](1, 2), t)
assertEqual(NewSetFromSlice[string]([]string{"a"}), NewSet[string]("a"), t)
assertEqual(NewSetFromSlice[string]([]string{"a", "b"}), NewSet[string]("a", "b"), t)
}
func Test_NewUnsafeSet(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
if a.Cardinality() != 0 {
t.Error("NewSet should start out as an empty set")
@ -175,7 +153,7 @@ func Test_RemoveUnsafeSet(t *testing.T) {
}
func Test_ContainsSet(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(71)
@ -199,7 +177,7 @@ func Test_ContainsSet(t *testing.T) {
}
func Test_ContainsUnsafeSet(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(71)
@ -267,7 +245,7 @@ func Test_ClearUnsafeSet(t *testing.T) {
}
func Test_CardinalitySet(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
if a.Cardinality() != 0 {
t.Error("set should be an empty set")
@ -299,7 +277,7 @@ func Test_CardinalitySet(t *testing.T) {
}
func Test_CardinalityUnsafeSet(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
if a.Cardinality() != 0 {
t.Error("set should be an empty set")
@ -333,7 +311,7 @@ func Test_CardinalityUnsafeSet(t *testing.T) {
func Test_SetIsSubset(t *testing.T) {
a := makeSetInt([]int{1, 2, 3, 5, 7})
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(3)
b.Add(5)
b.Add(7)
@ -373,7 +351,7 @@ func Test_SetIsProperSubset(t *testing.T) {
func Test_UnsafeSetIsSubset(t *testing.T) {
a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7})
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(3)
b.Add(5)
b.Add(7)
@ -391,7 +369,7 @@ func Test_UnsafeSetIsSubset(t *testing.T) {
func Test_UnsafeSetIsProperSubset(t *testing.T) {
a := makeUnsafeSetInt([]int{1, 2, 3, 5, 7})
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(7)
b.Add(1)
b.Add(5)
@ -416,14 +394,14 @@ func Test_UnsafeSetIsProperSubset(t *testing.T) {
}
func Test_SetIsSuperset(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(9)
a.Add(5)
a.Add(2)
a.Add(1)
a.Add(11)
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(5)
b.Add(2)
b.Add(11)
@ -440,12 +418,12 @@ func Test_SetIsSuperset(t *testing.T) {
}
func Test_SetIsProperSuperset(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(5)
a.Add(2)
a.Add(11)
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(2)
b.Add(5)
b.Add(11)
@ -477,14 +455,14 @@ func Test_SetIsProperSuperset(t *testing.T) {
}
func Test_UnsafeSetIsSuperset(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(9)
a.Add(5)
a.Add(2)
a.Add(1)
a.Add(11)
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(5)
b.Add(2)
b.Add(11)
@ -501,12 +479,12 @@ func Test_UnsafeSetIsSuperset(t *testing.T) {
}
func Test_UnsafeSetIsProperSuperset(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(5)
a.Add(2)
a.Add(11)
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(2)
b.Add(5)
b.Add(11)
@ -538,9 +516,9 @@ func Test_UnsafeSetIsProperSuperset(t *testing.T) {
}
func Test_SetUnion(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(1)
b.Add(2)
b.Add(3)
@ -553,7 +531,7 @@ func Test_SetUnion(t *testing.T) {
t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
}
d := NewSetGeneric[int]()
d := NewSet[int]()
d.Add(10)
d.Add(14)
d.Add(0)
@ -563,7 +541,7 @@ func Test_SetUnion(t *testing.T) {
t.Error("set e should should have 8 elements in it after being unioned with set c to d")
}
f := NewSetGeneric[int]()
f := NewSet[int]()
f.Add(14)
f.Add(3)
@ -574,9 +552,9 @@ func Test_SetUnion(t *testing.T) {
}
func Test_UnsafeSetUnion(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(1)
b.Add(2)
b.Add(3)
@ -589,7 +567,7 @@ func Test_UnsafeSetUnion(t *testing.T) {
t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
}
d := NewThreadUnsafeSetGeneric[int]()
d := NewThreadUnsafeSet[int]()
d.Add(10)
d.Add(14)
d.Add(0)
@ -599,7 +577,7 @@ func Test_UnsafeSetUnion(t *testing.T) {
t.Error("set e should should have 8 elements in it after being unioned with set c to d")
}
f := NewThreadUnsafeSetGeneric[int]()
f := NewThreadUnsafeSet[int]()
f.Add(14)
f.Add(3)
@ -610,12 +588,12 @@ func Test_UnsafeSetUnion(t *testing.T) {
}
func Test_SetIntersect(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(1)
a.Add(3)
a.Add(5)
b := NewSetGeneric[int]()
b := NewSet[int]()
a.Add(2)
a.Add(4)
a.Add(6)
@ -637,12 +615,12 @@ func Test_SetIntersect(t *testing.T) {
}
func Test_UnsafeSetIntersect(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(1)
a.Add(3)
a.Add(5)
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
a.Add(2)
a.Add(4)
a.Add(6)
@ -664,12 +642,12 @@ func Test_UnsafeSetIntersect(t *testing.T) {
}
func Test_SetDifference(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(1)
a.Add(2)
a.Add(3)
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(1)
b.Add(3)
b.Add(4)
@ -685,12 +663,12 @@ func Test_SetDifference(t *testing.T) {
}
func Test_UnsafeSetDifference(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(1)
a.Add(2)
a.Add(3)
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(1)
b.Add(3)
b.Add(4)
@ -706,13 +684,13 @@ func Test_UnsafeSetDifference(t *testing.T) {
}
func Test_SetSymmetricDifference(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(1)
a.Add(2)
a.Add(3)
a.Add(45)
b := NewSetGeneric[int]()
b := NewSet[int]()
b.Add(1)
b.Add(3)
b.Add(4)
@ -728,13 +706,13 @@ func Test_SetSymmetricDifference(t *testing.T) {
}
func Test_UnsafeSetSymmetricDifference(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(1)
a.Add(2)
a.Add(3)
a.Add(45)
b := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSet[int]()
b.Add(1)
b.Add(3)
b.Add(4)
@ -750,8 +728,8 @@ func Test_UnsafeSetSymmetricDifference(t *testing.T) {
}
func Test_SetEqual(t *testing.T) {
a := NewSetGeneric[int]()
b := NewSetGeneric[int]()
a := NewSet[int]()
b := NewSet[int]()
if !a.Equal(b) {
t.Error("Both a and b are empty sets, and should be equal")
@ -787,8 +765,8 @@ func Test_SetEqual(t *testing.T) {
}
func Test_UnsafeSetEqual(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
b := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
b := NewThreadUnsafeSet[int]()
if !a.Equal(b) {
t.Error("Both a and b are empty sets, and should be equal")
@ -824,7 +802,7 @@ func Test_UnsafeSetEqual(t *testing.T) {
}
func Test_SetClone(t *testing.T) {
a := NewSetGeneric[int]()
a := NewSet[int]()
a.Add(1)
a.Add(2)
@ -848,7 +826,7 @@ func Test_SetClone(t *testing.T) {
}
func Test_UnsafeSetClone(t *testing.T) {
a := NewThreadUnsafeSetGeneric[int]()
a := NewThreadUnsafeSet[int]()
a.Add(1)
a.Add(2)
@ -872,14 +850,14 @@ func Test_UnsafeSetClone(t *testing.T) {
}
func Test_Each(t *testing.T) {
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("Z")
a.Add("Y")
a.Add("X")
a.Add("W")
b := NewSetGeneric[string]()
b := NewSet[string]()
a.Each(func(elem string) bool {
b.Add(elem)
return false
@ -903,14 +881,14 @@ func Test_Each(t *testing.T) {
}
func Test_Iter(t *testing.T) {
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("Z")
a.Add("Y")
a.Add("X")
a.Add("W")
b := NewSetGeneric[string]()
b := NewSet[string]()
for val := range a.Iter() {
b.Add(val)
}
@ -921,14 +899,14 @@ func Test_Iter(t *testing.T) {
}
func Test_UnsafeIter(t *testing.T) {
a := NewThreadUnsafeSet()
a := NewThreadUnsafeSet[string]()
a.Add("Z")
a.Add("Y")
a.Add("X")
a.Add("W")
b := NewThreadUnsafeSet()
b := NewThreadUnsafeSet[string]()
for val := range a.Iter() {
b.Add(val)
}
@ -939,14 +917,14 @@ func Test_UnsafeIter(t *testing.T) {
}
func Test_Iterator(t *testing.T) {
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("Z")
a.Add("Y")
a.Add("X")
a.Add("W")
b := NewSetGeneric[string]()
b := NewSet[string]()
for val := range a.Iterator().C {
b.Add(val)
}
@ -957,14 +935,14 @@ func Test_Iterator(t *testing.T) {
}
func Test_UnsafeIterator(t *testing.T) {
a := NewThreadUnsafeSetGeneric[string]()
a := NewThreadUnsafeSet[string]()
a.Add("Z")
a.Add("Y")
a.Add("X")
a.Add("W")
b := NewThreadUnsafeSetGeneric[string]()
b := NewThreadUnsafeSet[string]()
for val := range a.Iterator().C {
b.Add(val)
}
@ -975,7 +953,7 @@ func Test_UnsafeIterator(t *testing.T) {
}
func Test_IteratorStop(t *testing.T) {
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("Z")
a.Add("Y")
@ -990,14 +968,14 @@ func Test_IteratorStop(t *testing.T) {
}
func Test_PopSafe(t *testing.T) {
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("a")
a.Add("b")
a.Add("c")
a.Add("d")
captureSet := NewSetGeneric[any]()
captureSet := NewSet[any]()
captureSet.Add(a.Pop())
captureSet.Add(a.Pop())
captureSet.Add(a.Pop())
@ -1022,14 +1000,14 @@ func Test_PopSafe(t *testing.T) {
}
func Test_PopUnsafe(t *testing.T) {
a := NewThreadUnsafeSetGeneric[string]()
a := NewThreadUnsafeSet[string]()
a.Add("a")
a.Add("b")
a.Add("c")
a.Add("d")
captureSet := NewThreadUnsafeSetGeneric[any]()
captureSet := NewThreadUnsafeSet[any]()
captureSet.Add(a.Pop())
captureSet.Add(a.Pop())
captureSet.Add(a.Pop())
@ -1054,7 +1032,7 @@ func Test_PopUnsafe(t *testing.T) {
}
func Test_PowerSet(t *testing.T) {
a := NewThreadUnsafeSetGeneric[string]()
a := NewThreadUnsafeSet[string]()
a.Add("1")
a.Add("delta")
@ -1082,14 +1060,14 @@ func Test_PowerSetThreadSafe(t *testing.T) {
}
func Test_EmptySetProperties(t *testing.T) {
empty := NewSetGeneric[string]()
empty := NewSet[string]()
a := NewSetGeneric[string]()
a := NewSet[string]()
a.Add("1")
a.Add("foo")
a.Add("bar")
b := NewSetGeneric[string]()
b := NewSet[string]()
b.Add("one")
b.Add("two")
b.Add("3")
@ -1133,9 +1111,9 @@ func Test_EmptySetProperties(t *testing.T) {
}
func Test_CartesianProduct(t *testing.T) {
a := NewThreadUnsafeSetGeneric[any]()
b := NewThreadUnsafeSetGeneric[any]()
empty := NewThreadUnsafeSetGeneric[any]()
a := NewThreadUnsafeSet[any]()
b := NewThreadUnsafeSet[any]()
empty := NewThreadUnsafeSet[any]()
a.Add(1)
a.Add(2)

View File

@ -27,162 +27,165 @@ package mapset
import "sync"
type threadSafeSet struct {
s threadUnsafeSet
type threadSafeSet[T comparable] struct {
sync.RWMutex
uss threadUnsafeSet[T]
}
func newThreadSafeSet() threadSafeSet {
return threadSafeSet{s: newThreadUnsafeSet()}
func newThreadSafeSet[T comparable]() threadSafeSet[T] {
newUss := newThreadUnsafeSet[T]()
return threadSafeSet[T]{
uss: newUss,
}
}
func (set *threadSafeSet) Add(i interface{}) bool {
set.Lock()
ret := set.s.Add(i)
set.Unlock()
func (s *threadSafeSet[T]) Add(v T) bool {
s.Lock()
ret := s.uss.Add(v)
s.Unlock()
return ret
}
func (set *threadSafeSet) Contains(i ...interface{}) bool {
set.RLock()
ret := set.s.Contains(i...)
set.RUnlock()
func (s *threadSafeSet[T]) Contains(v ...T) bool {
s.RLock()
ret := s.uss.Contains(v...)
s.RUnlock()
return ret
}
func (set *threadSafeSet) IsSubset(other Set) bool {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) IsSubset(other Set[T]) bool {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
ret := set.s.IsSubset(&o.s)
set.RUnlock()
ret := s.uss.IsSubset(&o.uss)
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) IsProperSubset(other Set) bool {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) IsProperSubset(other Set[T]) bool {
o := other.(*threadSafeSet[T])
set.RLock()
defer set.RUnlock()
s.RLock()
defer s.RUnlock()
o.RLock()
defer o.RUnlock()
return set.s.IsProperSubset(&o.s)
return s.uss.IsProperSubset(&o.uss)
}
func (set *threadSafeSet) IsSuperset(other Set) bool {
return other.IsSubset(set)
func (s *threadSafeSet[T]) IsSuperset(other Set[T]) bool {
return other.IsSubset(s)
}
func (set *threadSafeSet) IsProperSuperset(other Set) bool {
return other.IsProperSubset(set)
func (s *threadSafeSet[T]) IsProperSuperset(other Set[T]) bool {
return other.IsProperSubset(s)
}
func (set *threadSafeSet) Union(other Set) Set {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) Union(other Set[T]) Set[T] {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeUnion}
set.RUnlock()
unsafeUnion := s.uss.Union(&o.uss).(*threadUnsafeSet[T])
ret := &threadSafeSet[T]{uss: *unsafeUnion}
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) Intersect(other Set) Set {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) Intersect(other Set[T]) Set[T] {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeIntersection}
set.RUnlock()
unsafeIntersection := s.uss.Intersect(&o.uss).(*threadUnsafeSet[T])
ret := &threadSafeSet[T]{uss: *unsafeIntersection}
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) Difference(other Set) Set {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) Difference(other Set[T]) Set[T] {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeDifference}
set.RUnlock()
unsafeDifference := s.uss.Difference(&o.uss).(*threadUnsafeSet[T])
ret := &threadSafeSet[T]{uss: *unsafeDifference}
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) SymmetricDifference(other Set) Set {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeDifference}
set.RUnlock()
unsafeDifference := s.uss.SymmetricDifference(&o.uss).(*threadUnsafeSet[T])
ret := &threadSafeSet[T]{uss: *unsafeDifference}
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) Clear() {
set.Lock()
set.s = newThreadUnsafeSet()
set.Unlock()
func (s *threadSafeSet[T]) Clear() {
s.Lock()
s.uss = newThreadUnsafeSet[T]()
s.Unlock()
}
func (set *threadSafeSet) Remove(i interface{}) {
set.Lock()
delete(set.s, i)
set.Unlock()
func (s *threadSafeSet[T]) Remove(v T) {
s.Lock()
delete(s.uss, v)
s.Unlock()
}
func (set *threadSafeSet) Cardinality() int {
set.RLock()
defer set.RUnlock()
return len(set.s)
func (s *threadSafeSet[T]) Cardinality() int {
s.RLock()
defer s.RUnlock()
return len(s.uss)
}
func (set *threadSafeSet) Each(cb func(interface{}) bool) {
set.RLock()
for elem := range set.s {
func (s *threadSafeSet[T]) Each(cb func(T) bool) {
s.RLock()
for elem := range s.uss {
if cb(elem) {
break
}
}
set.RUnlock()
s.RUnlock()
}
func (set *threadSafeSet) Iter() <-chan interface{} {
ch := make(chan interface{})
func (s *threadSafeSet[T]) Iter() <-chan T {
ch := make(chan T)
go func() {
set.RLock()
s.RLock()
for elem := range set.s {
for elem := range s.uss {
ch <- elem
}
close(ch)
set.RUnlock()
s.RUnlock()
}()
return ch
}
func (set *threadSafeSet) Iterator() *Iterator {
iterator, ch, stopCh := newIterator()
func (s *threadSafeSet[T]) Iterator() *Iterator[T] {
iterator, ch, stopCh := newIterator[T]()
go func() {
set.RLock()
s.RLock()
L:
for elem := range set.s {
for elem := range s.uss {
select {
case <-stopCh:
break L
@ -190,94 +193,95 @@ func (set *threadSafeSet) Iterator() *Iterator {
}
}
close(ch)
set.RUnlock()
s.RUnlock()
}()
return iterator
}
func (set *threadSafeSet) Equal(other Set) bool {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) Equal(other Set[T]) bool {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
ret := set.s.Equal(&o.s)
set.RUnlock()
ret := s.uss.Equal(&o.uss)
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) Clone() Set {
set.RLock()
func (s *threadSafeSet[T]) Clone() Set[T] {
s.RLock()
unsafeClone := set.s.Clone().(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeClone}
set.RUnlock()
unsafeClone := s.uss.Clone().(*threadUnsafeSet[T])
ret := &threadSafeSet[T]{uss: *unsafeClone}
s.RUnlock()
return ret
}
func (set *threadSafeSet) String() string {
set.RLock()
ret := set.s.String()
set.RUnlock()
func (s *threadSafeSet[T]) String() string {
s.RLock()
ret := s.uss.String()
s.RUnlock()
return ret
}
func (set *threadSafeSet) PowerSet() Set {
set.RLock()
unsafePowerSet := set.s.PowerSet().(*threadUnsafeSet)
set.RUnlock()
func (s *threadSafeSet[T]) PowerSet() Set[any] {
s.RLock()
unsafePowerSet := s.uss.PowerSet().(*threadUnsafeSet[any])
s.RUnlock()
ret := &threadSafeSet{s: newThreadUnsafeSet()}
ret := &threadSafeSet[any]{uss: newThreadUnsafeSet[any]()}
for subset := range unsafePowerSet.Iter() {
unsafeSubset := subset.(*threadUnsafeSet)
ret.Add(&threadSafeSet{s: *unsafeSubset})
unsafeSubset := subset.(*threadUnsafeSet[any])
ret.Add(&threadSafeSet[any]{uss: *unsafeSubset})
}
return ret
}
func (set *threadSafeSet) Pop() interface{} {
set.Lock()
defer set.Unlock()
return set.s.Pop()
func (s *threadSafeSet[T]) Pop() any {
s.Lock()
defer s.Unlock()
return s.uss.Pop()
}
func (set *threadSafeSet) CartesianProduct(other Set) Set {
o := other.(*threadSafeSet)
func (s *threadSafeSet[T]) CartesianProduct(other Set[T]) Set[any] {
o := other.(*threadSafeSet[T])
set.RLock()
s.RLock()
o.RLock()
unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
ret := &threadSafeSet{s: *unsafeCartProduct}
set.RUnlock()
unsafeCartProduct := s.uss.CartesianProduct(&o.uss).(*threadUnsafeSet[any])
ret := &threadSafeSet[any]{uss: *unsafeCartProduct}
s.RUnlock()
o.RUnlock()
return ret
}
func (set *threadSafeSet) ToSlice() []interface{} {
keys := make([]interface{}, 0, set.Cardinality())
set.RLock()
for elem := range set.s {
func (s *threadSafeSet[T]) ToSlice() []T {
keys := make([]T, 0, s.Cardinality())
s.RLock()
for elem := range s.uss {
keys = append(keys, elem)
}
set.RUnlock()
s.RUnlock()
return keys
}
func (set *threadSafeSet) MarshalJSON() ([]byte, error) {
set.RLock()
b, err := set.s.MarshalJSON()
set.RUnlock()
func (s *threadSafeSet[T]) MarshalJSON() ([]byte, error) {
s.RLock()
b, err := s.uss.MarshalJSON()
s.RUnlock()
return b, err
}
func (set *threadSafeSet) UnmarshalJSON(p []byte) error {
set.RLock()
err := set.s.UnmarshalJSON(p)
set.RUnlock()
func (s *threadSafeSet[T]) UnmarshalJSON(p []byte) error {
s.RLock()
err := s.uss.UnmarshalJSON(p)
s.RUnlock()
return err
}

View File

@ -1,287 +0,0 @@
/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package mapset
import "sync"
type threadSafeSetGeneric[T comparable] struct {
sync.RWMutex
uss threadUnsafeSetGeneric[T]
}
func newThreadSafeSetGeneric[T comparable]() threadSafeSetGeneric[T] {
newUss := newThreadUnsafeSetGeneric[T]()
return threadSafeSetGeneric[T]{
uss: newUss,
}
}
func (s *threadSafeSetGeneric[T]) Add(v T) bool {
s.Lock()
ret := s.uss.Add(v)
s.Unlock()
return ret
}
func (s *threadSafeSetGeneric[T]) Contains(v ...T) bool {
s.RLock()
ret := s.uss.Contains(v...)
s.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) IsSubset(other SetGeneric[T]) bool {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
ret := s.uss.IsSubset(&o.uss)
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) IsProperSubset(other SetGeneric[T]) bool {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
defer s.RUnlock()
o.RLock()
defer o.RUnlock()
return s.uss.IsProperSubset(&o.uss)
}
func (s *threadSafeSetGeneric[T]) IsSuperset(other SetGeneric[T]) bool {
return other.IsSubset(s)
}
func (s *threadSafeSetGeneric[T]) IsProperSuperset(other SetGeneric[T]) bool {
return other.IsProperSubset(s)
}
func (s *threadSafeSetGeneric[T]) Union(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
unsafeUnion := s.uss.Union(&o.uss).(*threadUnsafeSetGeneric[T])
ret := &threadSafeSetGeneric[T]{uss: *unsafeUnion}
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) Intersect(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
unsafeIntersection := s.uss.Intersect(&o.uss).(*threadUnsafeSetGeneric[T])
ret := &threadSafeSetGeneric[T]{uss: *unsafeIntersection}
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) Difference(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
unsafeDifference := s.uss.Difference(&o.uss).(*threadUnsafeSetGeneric[T])
ret := &threadSafeSetGeneric[T]{uss: *unsafeDifference}
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) SymmetricDifference(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
unsafeDifference := s.uss.SymmetricDifference(&o.uss).(*threadUnsafeSetGeneric[T])
ret := &threadSafeSetGeneric[T]{uss: *unsafeDifference}
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) Clear() {
s.Lock()
s.uss = newThreadUnsafeSetGeneric[T]()
s.Unlock()
}
func (s *threadSafeSetGeneric[T]) Remove(v T) {
s.Lock()
delete(s.uss, v)
s.Unlock()
}
func (s *threadSafeSetGeneric[T]) Cardinality() int {
s.RLock()
defer s.RUnlock()
return len(s.uss)
}
func (s *threadSafeSetGeneric[T]) Each(cb func(T) bool) {
s.RLock()
for elem := range s.uss {
if cb(elem) {
break
}
}
s.RUnlock()
}
func (s *threadSafeSetGeneric[T]) Iter() <-chan T {
ch := make(chan T)
go func() {
s.RLock()
for elem := range s.uss {
ch <- elem
}
close(ch)
s.RUnlock()
}()
return ch
}
func (s *threadSafeSetGeneric[T]) Iterator() *IteratorGeneric[T] {
iterator, ch, stopCh := newIteratorGeneric[T]()
go func() {
s.RLock()
L:
for elem := range s.uss {
select {
case <-stopCh:
break L
case ch <- elem:
}
}
close(ch)
s.RUnlock()
}()
return iterator
}
func (s *threadSafeSetGeneric[T]) Equal(other SetGeneric[T]) bool {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
ret := s.uss.Equal(&o.uss)
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) Clone() SetGeneric[T] {
s.RLock()
unsafeClone := s.uss.Clone().(*threadUnsafeSetGeneric[T])
ret := &threadSafeSetGeneric[T]{uss: *unsafeClone}
s.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) String() string {
s.RLock()
ret := s.uss.String()
s.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) PowerSet() SetGeneric[any] {
s.RLock()
unsafePowerSet := s.uss.PowerSet().(*threadUnsafeSetGeneric[any])
s.RUnlock()
ret := &threadSafeSetGeneric[any]{uss: newThreadUnsafeSetGeneric[any]()}
for subset := range unsafePowerSet.Iter() {
unsafeSubset := subset.(*threadUnsafeSetGeneric[any])
ret.Add(&threadSafeSetGeneric[any]{uss: *unsafeSubset})
}
return ret
}
func (s *threadSafeSetGeneric[T]) Pop() any {
s.Lock()
defer s.Unlock()
return s.uss.Pop()
}
func (s *threadSafeSetGeneric[T]) CartesianProduct(other SetGeneric[T]) SetGeneric[any] {
o := other.(*threadSafeSetGeneric[T])
s.RLock()
o.RLock()
unsafeCartProduct := s.uss.CartesianProduct(&o.uss).(*threadUnsafeSetGeneric[any])
ret := &threadSafeSetGeneric[any]{uss: *unsafeCartProduct}
s.RUnlock()
o.RUnlock()
return ret
}
func (s *threadSafeSetGeneric[T]) ToSlice() []T {
keys := make([]T, 0, s.Cardinality())
s.RLock()
for elem := range s.uss {
keys = append(keys, elem)
}
s.RUnlock()
return keys
}
func (s *threadSafeSetGeneric[T]) MarshalJSON() ([]byte, error) {
s.RLock()
b, err := s.uss.MarshalJSON()
s.RUnlock()
return b, err
}
func (s *threadSafeSetGeneric[T]) UnmarshalJSON(p []byte) error {
s.RLock()
err := s.uss.UnmarshalJSON(p)
s.RUnlock()
return err
}

View File

@ -39,7 +39,7 @@ const N = 1000
func Test_AddConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
var wg sync.WaitGroup
@ -62,7 +62,7 @@ func Test_AddConcurrent(t *testing.T) {
func Test_CardinalityConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
var wg sync.WaitGroup
wg.Add(1)
@ -86,7 +86,7 @@ func Test_CardinalityConcurrent(t *testing.T) {
func Test_ClearConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
var wg sync.WaitGroup
@ -107,7 +107,7 @@ func Test_ClearConcurrent(t *testing.T) {
func Test_CloneConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
@ -129,7 +129,7 @@ func Test_CloneConcurrent(t *testing.T) {
func Test_ContainsConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
integers := make([]int, 0)
for _, v := range ints {
@ -151,7 +151,7 @@ func Test_ContainsConcurrent(t *testing.T) {
func Test_DifferenceConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -172,7 +172,7 @@ func Test_DifferenceConcurrent(t *testing.T) {
func Test_EqualConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -193,7 +193,7 @@ func Test_EqualConcurrent(t *testing.T) {
func Test_IntersectConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -214,7 +214,7 @@ func Test_IntersectConcurrent(t *testing.T) {
func Test_IsSubsetConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -235,7 +235,7 @@ func Test_IsSubsetConcurrent(t *testing.T) {
func Test_IsProperSubsetConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -256,7 +256,7 @@ func Test_IsProperSubsetConcurrent(t *testing.T) {
func Test_IsSupersetConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -277,7 +277,7 @@ func Test_IsSupersetConcurrent(t *testing.T) {
func Test_IsProperSupersetConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -299,7 +299,7 @@ func Test_EachConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
concurrent := 10
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -327,7 +327,7 @@ func Test_EachConcurrent(t *testing.T) {
func Test_IterConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -360,7 +360,7 @@ func Test_IterConcurrent(t *testing.T) {
func Test_RemoveConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -384,7 +384,7 @@ func Test_RemoveConcurrent(t *testing.T) {
func Test_StringConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -404,7 +404,7 @@ func Test_StringConcurrent(t *testing.T) {
func Test_SymmetricDifferenceConcurrent(t *testing.T) {
runtime.GOMAXPROCS(2)
s, ss := NewSetGeneric[int](), NewSetGeneric[int]()
s, ss := NewSet[int](), NewSet[int]()
ints := rand.Perm(N)
for _, v := range ints {
s.Add(v)
@ -425,7 +425,7 @@ func Test_SymmetricDifferenceConcurrent(t *testing.T) {
func Test_ToSlice(t *testing.T) {
runtime.GOMAXPROCS(2)
s := NewSetGeneric[int]()
s := NewSet[int]()
ints := rand.Perm(N)
var wg sync.WaitGroup
@ -456,7 +456,7 @@ func Test_ToSliceDeadlock(t *testing.T) {
runtime.GOMAXPROCS(2)
var wg sync.WaitGroup
set := NewSetGeneric[int]()
set := NewSet[int]()
workers := 10
wg.Add(workers)
for i := 1; i <= workers; i++ {
@ -473,7 +473,7 @@ func Test_ToSliceDeadlock(t *testing.T) {
func Test_UnmarshalJSON(t *testing.T) {
s := []byte(`["test", 1, 2, 3]`) //,["4,5,6"]]`)
expected := NewSetFromSliceGeneric[any](
expected := NewSetFromSlice[any](
[]any{
json.Number("1"),
json.Number("2"),
@ -481,7 +481,7 @@ func Test_UnmarshalJSON(t *testing.T) {
"test",
},
)
actual := NewSetGeneric[any]()
actual := NewSet[any]()
err := json.Unmarshal(s, actual)
if err != nil {
t.Errorf("Error should be nil: %v", err)
@ -493,7 +493,7 @@ func Test_UnmarshalJSON(t *testing.T) {
}
func Test_MarshalJSON(t *testing.T) {
expected := NewSetFromSliceGeneric[any](
expected := NewSetFromSlice[any](
[]any{
json.Number("1"),
"test",
@ -501,7 +501,7 @@ func Test_MarshalJSON(t *testing.T) {
)
b, err := json.Marshal(
NewSetFromSliceGeneric[any](
NewSetFromSlice[any](
[]any{
1,
"test",
@ -512,7 +512,7 @@ func Test_MarshalJSON(t *testing.T) {
t.Errorf("Error should be nil: %v", err)
}
actual := NewSetGeneric[any]()
actual := NewSet[any]()
err = json.Unmarshal(b, actual)
if err != nil {
t.Errorf("Error should be nil: %v", err)

View File

@ -26,27 +26,21 @@ SOFTWARE.
package mapset
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
"strings"
"encoding/json"
"bytes"
)
type threadUnsafeSet map[interface{}]struct{}
// An OrderedPair represents a 2-tuple of values.
type OrderedPair struct {
First interface{}
Second interface{}
}
func newThreadUnsafeSet() threadUnsafeSet {
return make(threadUnsafeSet)
type OrderedPair[T comparable] struct {
First T
Second T
}
// Equal says whether two 2-tuples contain the same values in the same order.
func (pair *OrderedPair) Equal(other OrderedPair) bool {
func (pair *OrderedPair[T]) Equal(other OrderedPair[T]) bool {
if pair.First == other.First &&
pair.Second == other.Second {
return true
@ -55,31 +49,109 @@ func (pair *OrderedPair) Equal(other OrderedPair) bool {
return false
}
func (set *threadUnsafeSet) Add(i interface{}) bool {
_, found := (*set)[i]
// String outputs a 2-tuple in the form "(A, B)".
func (pair OrderedPair[T]) String() string {
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
}
type threadUnsafeSet[T comparable] map[T]struct{}
// // An OrderedPair represents a 2-tuple of values.
// type OrderedPair struct {
// First interface{}
// Second interface{}
// }
// Assert concrete type:threadUnsafeSet adheres to Set interface.
var _ Set[string] = (*threadUnsafeSet[string])(nil)
func newThreadUnsafeSet[T comparable]() threadUnsafeSet[T] {
return make(threadUnsafeSet[T])
}
func (s *threadUnsafeSet[T]) Add(v T) bool {
_, found := (*s)[v]
if found {
return false //False if it existed already
}
(*set)[i] = struct{}{}
(*s)[v] = struct{}{}
return true
}
func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
for _, val := range i {
if _, ok := (*set)[val]; !ok {
func (s *threadUnsafeSet[T]) Cardinality() int {
return len(*s)
}
func (s *threadUnsafeSet[T]) CartesianProduct(other Set[T]) Set[any] {
o := other.(*threadUnsafeSet[T])
// NOTE: limitation with Go s or of my knowledge of Go s?
// I can't seem to declare this without an instantiation cycle.
//cartProduct := NewThreadUnsafeSet[OrderedPair[T]]()
// So here is my crime against humanity.
cartProduct := NewThreadUnsafeSet[any]()
for i := range *s {
for j := range *o {
elem := OrderedPair[T]{First: i, Second: j}
cartProduct.Add(elem)
}
}
return cartProduct
}
func (s *threadUnsafeSet[T]) Clear() {
*s = newThreadUnsafeSet[T]()
}
func (s *threadUnsafeSet[T]) Clone() Set[T] {
clonedSet := newThreadUnsafeSet[T]()
for elem := range *s {
clonedSet.Add(elem)
}
return &clonedSet
}
func (s *threadUnsafeSet[T]) Contains(v ...T) bool {
for _, val := range v {
if _, ok := (*s)[val]; !ok {
return false
}
}
return true
}
func (set *threadUnsafeSet) IsSubset(other Set) bool {
_ = other.(*threadUnsafeSet)
if set.Cardinality() > other.Cardinality() {
func (s *threadUnsafeSet[T]) Difference(other Set[T]) Set[T] {
_ = other.(*threadUnsafeSet[T])
diff := newThreadUnsafeSet[T]()
for elem := range *s {
if !other.Contains(elem) {
diff.Add(elem)
}
}
return &diff
}
func (s *threadUnsafeSet[T]) Each(cb func(T) bool) {
for elem := range *s {
if cb(elem) {
break
}
}
}
func (s *threadUnsafeSet[T]) Equal(other Set[T]) bool {
_ = other.(*threadUnsafeSet[T])
if s.Cardinality() != other.Cardinality() {
return false
}
for elem := range *set {
for elem := range *s {
if !other.Contains(elem) {
return false
}
@ -87,46 +159,20 @@ func (set *threadUnsafeSet) IsSubset(other Set) bool {
return true
}
func (set *threadUnsafeSet) IsProperSubset(other Set) bool {
return set.IsSubset(other) && !set.Equal(other)
}
func (s *threadUnsafeSet[T]) Intersect(other Set[T]) Set[T] {
o := other.(*threadUnsafeSet[T])
func (set *threadUnsafeSet) IsSuperset(other Set) bool {
return other.IsSubset(set)
}
func (set *threadUnsafeSet) IsProperSuperset(other Set) bool {
return set.IsSuperset(other) && !set.Equal(other)
}
func (set *threadUnsafeSet) Union(other Set) Set {
o := other.(*threadUnsafeSet)
unionedSet := newThreadUnsafeSet()
for elem := range *set {
unionedSet.Add(elem)
}
for elem := range *o {
unionedSet.Add(elem)
}
return &unionedSet
}
func (set *threadUnsafeSet) Intersect(other Set) Set {
o := other.(*threadUnsafeSet)
intersection := newThreadUnsafeSet()
intersection := newThreadUnsafeSet[T]()
// loop over smaller set
if set.Cardinality() < other.Cardinality() {
for elem := range *set {
if s.Cardinality() < other.Cardinality() {
for elem := range *s {
if other.Contains(elem) {
intersection.Add(elem)
}
}
} else {
for elem := range *o {
if set.Contains(elem) {
if s.Contains(elem) {
intersection.Add(elem)
}
}
@ -134,50 +180,35 @@ func (set *threadUnsafeSet) Intersect(other Set) Set {
return &intersection
}
func (set *threadUnsafeSet) Difference(other Set) Set {
_ = other.(*threadUnsafeSet)
func (s *threadUnsafeSet[T]) IsProperSubset(other Set[T]) bool {
return s.IsSubset(other) && !s.Equal(other)
}
difference := newThreadUnsafeSet()
for elem := range *set {
func (s *threadUnsafeSet[T]) IsProperSuperset(other Set[T]) bool {
return s.IsSuperset(other) && !s.Equal(other)
}
func (s *threadUnsafeSet[T]) IsSubset(other Set[T]) bool {
_ = other.(*threadUnsafeSet[T])
if s.Cardinality() > other.Cardinality() {
return false
}
for elem := range *s {
if !other.Contains(elem) {
difference.Add(elem)
return false
}
}
return &difference
return true
}
func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
_ = other.(*threadUnsafeSet)
aDiff := set.Difference(other)
bDiff := other.Difference(set)
return aDiff.Union(bDiff)
func (s *threadUnsafeSet[T]) IsSuperset(other Set[T]) bool {
return other.IsSubset(s)
}
func (set *threadUnsafeSet) Clear() {
*set = newThreadUnsafeSet()
}
func (set *threadUnsafeSet) Remove(i interface{}) {
delete(*set, i)
}
func (set *threadUnsafeSet) Cardinality() int {
return len(*set)
}
func (set *threadUnsafeSet) Each(cb func(interface{}) bool) {
for elem := range *set {
if cb(elem) {
break
}
}
}
func (set *threadUnsafeSet) Iter() <-chan interface{} {
ch := make(chan interface{})
func (s *threadUnsafeSet[T]) Iter() <-chan T {
ch := make(chan T)
go func() {
for elem := range *set {
for elem := range *s {
ch <- elem
}
close(ch)
@ -186,12 +217,12 @@ func (set *threadUnsafeSet) Iter() <-chan interface{} {
return ch
}
func (set *threadUnsafeSet) Iterator() *Iterator {
iterator, ch, stopCh := newIterator()
func (s *threadUnsafeSet[T]) Iterator() *Iterator[T] {
iterator, ch, stopCh := newIterator[T]()
go func() {
L:
for elem := range *set {
for elem := range *s {
select {
case <-stopCh:
break L
@ -204,67 +235,34 @@ func (set *threadUnsafeSet) Iterator() *Iterator {
return iterator
}
func (set *threadUnsafeSet) Equal(other Set) bool {
_ = other.(*threadUnsafeSet)
if set.Cardinality() != other.Cardinality() {
return false
}
for elem := range *set {
if !other.Contains(elem) {
return false
}
}
return true
}
func (set *threadUnsafeSet) Clone() Set {
clonedSet := newThreadUnsafeSet()
for elem := range *set {
clonedSet.Add(elem)
}
return &clonedSet
}
func (set *threadUnsafeSet) String() string {
items := make([]string, 0, len(*set))
for elem := range *set {
items = append(items, fmt.Sprintf("%v", elem))
}
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
}
// String outputs a 2-tuple in the form "(A, B)".
func (pair OrderedPair) String() string {
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
}
func (set *threadUnsafeSet) Pop() interface{} {
for item := range *set {
delete(*set, item)
// TODO: how can we make this properly , return T but can't return nil.
func (s *threadUnsafeSet[T]) Pop() any {
for item := range *s {
delete(*s, item)
return item
}
return nil
}
func (set *threadUnsafeSet) PowerSet() Set {
powSet := NewThreadUnsafeSet()
nullset := newThreadUnsafeSet()
func (s *threadUnsafeSet[T]) PowerSet() Set[any] {
// The type must be any comparable so we have to dumb down to any.
powSet := NewThreadUnsafeSet[any]()
nullset := newThreadUnsafeSet[T]()
powSet.Add(&nullset)
for es := range *set {
u := newThreadUnsafeSet()
for es := range *s {
u := newThreadUnsafeSet[any]()
j := powSet.Iter()
for er := range j {
p := newThreadUnsafeSet()
p := newThreadUnsafeSet[T]()
if reflect.TypeOf(er).Name() == "" {
k := er.(*threadUnsafeSet)
k := er.(*threadUnsafeSet[T])
for ek := range *(k) {
p.Add(ek)
}
} else {
p.Add(er)
p.Add(er.(T))
}
p.Add(es)
u.Add(&p)
@ -276,34 +274,55 @@ func (set *threadUnsafeSet) PowerSet() Set {
return powSet
}
func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
o := other.(*threadUnsafeSet)
cartProduct := NewThreadUnsafeSet()
for i := range *set {
for j := range *o {
elem := OrderedPair{First: i, Second: j}
cartProduct.Add(elem)
}
}
return cartProduct
func (s *threadUnsafeSet[T]) Remove(v T) {
delete(*s, v)
}
func (set *threadUnsafeSet) ToSlice() []interface{} {
keys := make([]interface{}, 0, set.Cardinality())
for elem := range *set {
func (s *threadUnsafeSet[T]) String() string {
items := make([]string, 0, len(*s))
for elem := range *s {
items = append(items, fmt.Sprintf("%v", elem))
}
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
}
func (s *threadUnsafeSet[T]) SymmetricDifference(other Set[T]) Set[T] {
_ = other.(*threadUnsafeSet[T])
a := s.Difference(other)
b := other.Difference(s)
return a.Union(b)
}
func (s *threadUnsafeSet[T]) ToSlice() []T {
keys := make([]T, 0, s.Cardinality())
for elem := range *s {
keys = append(keys, elem)
}
return keys
}
// MarshalJSON creates a JSON array from the set, it marshals all elements
func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
items := make([]string, 0, set.Cardinality())
func (s *threadUnsafeSet[T]) Union(other Set[T]) Set[T] {
o := other.(*threadUnsafeSet[T])
for elem := range *set {
unionedSet := newThreadUnsafeSet[T]()
for elem := range *s {
unionedSet.Add(elem)
}
for elem := range *o {
unionedSet.Add(elem)
}
return &unionedSet
}
// MarshalJSON creates a JSON array from the set, it marshals all elements
func (s *threadUnsafeSet[T]) MarshalJSON() ([]byte, error) {
items := make([]string, 0, s.Cardinality())
for elem := range *s {
b, err := json.Marshal(elem)
if err != nil {
return nil, err
@ -317,8 +336,8 @@ func (set *threadUnsafeSet) MarshalJSON() ([]byte, error) {
// UnmarshalJSON recreates a set from a JSON array, it only decodes
// primitive types. Numbers are decoded as json.Number.
func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
var i []interface{}
func (s *threadUnsafeSet[T]) UnmarshalJSON(b []byte) error {
var i []any
d := json.NewDecoder(bytes.NewReader(b))
d.UseNumber()
@ -329,12 +348,13 @@ func (set *threadUnsafeSet) UnmarshalJSON(b []byte) error {
for _, v := range i {
switch t := v.(type) {
case []interface{}, map[string]interface{}:
continue
case T:
s.Add(t)
default:
set.Add(t)
// anything else must be skipped.
continue
}
}
return nil
}
}

View File

@ -1,360 +0,0 @@
/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package mapset
import (
"fmt"
"reflect"
"strings"
"encoding/json"
"bytes"
)
// An OrderedPairGeneric represents a 2-tuple of values.
type OrderedPairGeneric[T comparable] struct {
First T
Second T
}
// Equal says whether two 2-tuples contain the same values in the same order.
func (pair *OrderedPairGeneric[T]) Equal(other OrderedPairGeneric[T]) bool {
if pair.First == other.First &&
pair.Second == other.Second {
return true
}
return false
}
// String outputs a 2-tuple in the form "(A, B)".
func (pair OrderedPairGeneric[T]) String() string {
return fmt.Sprintf("(%v, %v)", pair.First, pair.Second)
}
type threadUnsafeSetGeneric[T comparable] map[T]struct{}
// // An OrderedPair represents a 2-tuple of values.
// type OrderedPair struct {
// First interface{}
// Second interface{}
// }
// Assert concrete type:threadUnsafeSetGeneric adheres to SetGeneric interface.
var _ SetGeneric[string] = (*threadUnsafeSetGeneric[string])(nil)
func newThreadUnsafeSetGeneric[T comparable]() threadUnsafeSetGeneric[T] {
return make(threadUnsafeSetGeneric[T])
}
func (s *threadUnsafeSetGeneric[T]) Add(v T) bool {
_, found := (*s)[v]
if found {
return false //False if it existed already
}
(*s)[v] = struct{}{}
return true
}
func (s *threadUnsafeSetGeneric[T]) Cardinality() int {
return len(*s)
}
func (s *threadUnsafeSetGeneric[T]) CartesianProduct(other SetGeneric[T]) SetGeneric[any] {
o := other.(*threadUnsafeSetGeneric[T])
// NOTE: limitation with Go generics or of my knowledge of Go generics?
// I can't seem to declare this without an instantiation cycle.
//cartProduct := NewThreadUnsafeSetGeneric[OrderedPairGeneric[T]]()
// So here is my crime against humanity.
cartProduct := NewThreadUnsafeSetGeneric[any]()
for i := range *s {
for j := range *o {
elem := OrderedPairGeneric[T]{First: i, Second: j}
cartProduct.Add(elem)
}
}
return cartProduct
}
func (s *threadUnsafeSetGeneric[T]) Clear() {
*s = newThreadUnsafeSetGeneric[T]()
}
func (s *threadUnsafeSetGeneric[T]) Clone() SetGeneric[T] {
clonedSet := newThreadUnsafeSetGeneric[T]()
for elem := range *s {
clonedSet.Add(elem)
}
return &clonedSet
}
func (s *threadUnsafeSetGeneric[T]) Contains(v ...T) bool {
for _, val := range v {
if _, ok := (*s)[val]; !ok {
return false
}
}
return true
}
func (s *threadUnsafeSetGeneric[T]) Difference(other SetGeneric[T]) SetGeneric[T] {
_ = other.(*threadUnsafeSetGeneric[T])
diff := newThreadUnsafeSetGeneric[T]()
for elem := range *s {
if !other.Contains(elem) {
diff.Add(elem)
}
}
return &diff
}
func (s *threadUnsafeSetGeneric[T]) Each(cb func(T) bool) {
for elem := range *s {
if cb(elem) {
break
}
}
}
func (s *threadUnsafeSetGeneric[T]) Equal(other SetGeneric[T]) bool {
_ = other.(*threadUnsafeSetGeneric[T])
if s.Cardinality() != other.Cardinality() {
return false
}
for elem := range *s {
if !other.Contains(elem) {
return false
}
}
return true
}
func (s *threadUnsafeSetGeneric[T]) Intersect(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadUnsafeSetGeneric[T])
intersection := newThreadUnsafeSetGeneric[T]()
// loop over smaller set
if s.Cardinality() < other.Cardinality() {
for elem := range *s {
if other.Contains(elem) {
intersection.Add(elem)
}
}
} else {
for elem := range *o {
if s.Contains(elem) {
intersection.Add(elem)
}
}
}
return &intersection
}
func (s *threadUnsafeSetGeneric[T]) IsProperSubset(other SetGeneric[T]) bool {
return s.IsSubset(other) && !s.Equal(other)
}
func (s *threadUnsafeSetGeneric[T]) IsProperSuperset(other SetGeneric[T]) bool {
return s.IsSuperset(other) && !s.Equal(other)
}
func (s *threadUnsafeSetGeneric[T]) IsSubset(other SetGeneric[T]) bool {
_ = other.(*threadUnsafeSetGeneric[T])
if s.Cardinality() > other.Cardinality() {
return false
}
for elem := range *s {
if !other.Contains(elem) {
return false
}
}
return true
}
func (s *threadUnsafeSetGeneric[T]) IsSuperset(other SetGeneric[T]) bool {
return other.IsSubset(s)
}
func (s *threadUnsafeSetGeneric[T]) Iter() <-chan T {
ch := make(chan T)
go func() {
for elem := range *s {
ch <- elem
}
close(ch)
}()
return ch
}
func (s *threadUnsafeSetGeneric[T]) Iterator() *IteratorGeneric[T] {
iterator, ch, stopCh := newIteratorGeneric[T]()
go func() {
L:
for elem := range *s {
select {
case <-stopCh:
break L
case ch <- elem:
}
}
close(ch)
}()
return iterator
}
// TODO: how can we make this properly generic, return T but can't return nil.
func (s *threadUnsafeSetGeneric[T]) Pop() any {
for item := range *s {
delete(*s, item)
return item
}
return nil
}
func (s *threadUnsafeSetGeneric[T]) PowerSet() SetGeneric[any] {
// The type must be any comparable so we have to dumb down to any.
powSet := NewThreadUnsafeSetGeneric[any]()
nullset := newThreadUnsafeSetGeneric[T]()
powSet.Add(&nullset)
for es := range *s {
u := newThreadUnsafeSetGeneric[any]()
j := powSet.Iter()
for er := range j {
p := newThreadUnsafeSetGeneric[T]()
if reflect.TypeOf(er).Name() == "" {
k := er.(*threadUnsafeSetGeneric[T])
for ek := range *(k) {
p.Add(ek)
}
} else {
p.Add(er.(T))
}
p.Add(es)
u.Add(&p)
}
powSet = powSet.Union(&u)
}
return powSet
}
func (s *threadUnsafeSetGeneric[T]) Remove(v T) {
delete(*s, v)
}
func (s *threadUnsafeSetGeneric[T]) String() string {
items := make([]string, 0, len(*s))
for elem := range *s {
items = append(items, fmt.Sprintf("%v", elem))
}
return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
}
func (s *threadUnsafeSetGeneric[T]) SymmetricDifference(other SetGeneric[T]) SetGeneric[T] {
_ = other.(*threadUnsafeSetGeneric[T])
a := s.Difference(other)
b := other.Difference(s)
return a.Union(b)
}
func (s *threadUnsafeSetGeneric[T]) ToSlice() []T {
keys := make([]T, 0, s.Cardinality())
for elem := range *s {
keys = append(keys, elem)
}
return keys
}
func (s *threadUnsafeSetGeneric[T]) Union(other SetGeneric[T]) SetGeneric[T] {
o := other.(*threadUnsafeSetGeneric[T])
unionedSet := newThreadUnsafeSetGeneric[T]()
for elem := range *s {
unionedSet.Add(elem)
}
for elem := range *o {
unionedSet.Add(elem)
}
return &unionedSet
}
// MarshalJSON creates a JSON array from the set, it marshals all elements
func (s *threadUnsafeSetGeneric[T]) MarshalJSON() ([]byte, error) {
items := make([]string, 0, s.Cardinality())
for elem := range *s {
b, err := json.Marshal(elem)
if err != nil {
return nil, err
}
items = append(items, string(b))
}
return []byte(fmt.Sprintf("[%s]", strings.Join(items, ","))), nil
}
// UnmarshalJSON recreates a set from a JSON array, it only decodes
// primitive types. Numbers are decoded as json.Number.
func (s *threadUnsafeSetGeneric[T]) UnmarshalJSON(b []byte) error {
var i []any
d := json.NewDecoder(bytes.NewReader(b))
d.UseNumber()
err := d.Decode(&i)
if err != nil {
return err
}
for _, v := range i {
switch t := v.(type) {
case T:
s.Add(t)
default:
// anything else must be skipped.
continue
}
}
return nil
}

View File

@ -1,72 +0,0 @@
/*
Open Source Initiative OSI - The MIT License (MIT):Licensing
The MIT License (MIT)
Copyright (c) 2013 - 2022 Ralph Caraveo (deckarep@gmail.com)
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
of the Software, and to permit persons to whom the Software is furnished to do
so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
package mapset
import (
"fmt"
"testing"
)
// Want to test numbers, strings and some kind of struct.
// That will be good enough.
func Test_Generic(t *testing.T) {
a := newThreadUnsafeSetGeneric[int]()
if a.Cardinality() != 0 {
t.Error("should be empty")
}
a.Add(5)
if a.Cardinality() != 1 {
t.Error("should have one element")
}
a.Add(4)
if a.Cardinality() != 2 {
t.Error("should have 2 elements")
}
s := a.ToSlice()
fmt.Println(s)
}
func Test_Generic_String(t *testing.T) {
a := newThreadUnsafeSetGeneric[int]()
a.Add(5)
a.Add(4)
fmt.Println(a.String())
}
func Test_Powerset(t *testing.T) {
a := newThreadUnsafeSetGeneric[string]()
a.Add("x")
a.Add("y")
a.Add("z")
ps := a.PowerSet()
fmt.Println(ps)
}