Java 中的集合(set)去重很方便,PHP 中的数组值去重,就更加方便,一个函数搞定:array_unique(),Golang 中就比较苦逼了,官方没有提供对“切片去重”的功能,而项目中,又经常用到这个功能,,我们可以模拟 Java 集合的功能,实现 Golang 版集合的同时,顺便把 去重 和 排序 做了,它的主要实现原理是:利用 map 数据 不允许键重名 的特点,参考代码如下:
# set_int.go
package utils
import (
"sort"
"sync"
)
// 实现 set 集合,变相实现 切片去重
// by php-note.com
type IntSet struct {
m map[int]bool
sync.RWMutex
}
func NewIntSet() *IntSet {
return &IntSet{
m: map[int]bool{},
}
}
func (s *IntSet) Add(items ...int) {
s.Lock()
defer s.Unlock()
if len(items) == 0 {
return
}
for _, item := range items {
s.m[item] = true
}
}
func (s *IntSet) Remove(items ...int) {
s.Lock()
defer s.Unlock()
if len(items) == 0 {
return
}
for _, item := range items {
delete(s.m, item)
}
}
func (s *IntSet) Has(item int) bool {
s.RLock()
defer s.RUnlock()
_, ok := s.m[item]
return ok
}
func (s *IntSet) Len() int {
return len(s.List())
}
func (s *IntSet) Clear() {
s.Lock()
defer s.Unlock()
s.m = map[int]bool{}
}
func (s *IntSet) IsEmpty() bool {
if s.Len() == 0 {
return true
}
return false
}
func (s *IntSet) List() []int {
s.RLock()
defer s.RUnlock()
list := []int{}
for item := range s.m {
list = append(list, item)
}
return list
}
func (s *IntSet) SortList() []int {
s.RLock()
defer s.RUnlock()
list := []int{}
for item := range s.m {
list = append(list, item)
}
sort.Ints(list)
return list
}
# set_string.go
package utils
import (
"sort"
"sync"
)
// 实现 set 集合,变相实现 切片去重
// by php-note.com
type StringSet struct {
m map[string]bool
sync.RWMutex
}
func NewStringSet() *StringSet {
return &StringSet{
m: map[string]bool{},
}
}
func (s *StringSet) Add(items ...string) {
s.Lock()
defer s.Unlock()
if len(items) == 0 {
return
}
for _, item := range items {
s.m[item] = true
}
}
func (s *StringSet) Remove(items ...string) {
s.Lock()
defer s.Unlock()
if len(items) == 0 {
return
}
for _, item := range items {
delete(s.m, item)
}
}
func (s *StringSet) Has(item string) bool {
s.RLock()
defer s.RUnlock()
_, ok := s.m[item]
return ok
}
func (s *StringSet) Len() int {
return len(s.List())
}
func (s *StringSet) Clear() {
s.Lock()
defer s.Unlock()
s.m = map[string]bool{}
}
func (s *StringSet) IsEmpty() bool {
if s.Len() == 0 {
return true
}
return false
}
func (s *StringSet) List() []string {
s.RLock()
defer s.RUnlock()
list := []string{}
for item := range s.m {
list = append(list, item)
}
return list
}
func (s *StringSet) SortList() []string {
s.RLock()
defer s.RUnlock()
list := []string{}
for item := range s.m {
list = append(list, item)
}
sort.Strings(list)
return list
}
# 应用示例:
package main
import (
"utils"
"fmt"
)
func main() {
// int 集合
s := utils.NewIntSet()
// 添加数据
s.Add(5, 2, 4, 3, 5, 6, 7)
// 去重后的值
fmt.Println(s.List())
// 排序后的值
fmt.Println(s.SortList())
// string 集合
s2 := utils.NewStringSet()
// 添加数据
s2.Add("wen", "jian", "bao", "study", "goalng", "bao", "jian")
// 去重后的值
fmt.Println(s2.List())
// 排序后的值
fmt.Println(s2.SortList())
}