Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > go语言 set集合

go语言中数据接口set集合的实现

作者:SRExianxian

set集合是一种常见的数据结构,它代表了一个唯一元素的集合,本文主要介绍了set的基本特性,包括唯一性、无序性、可变性和集合运算,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

概述

set 是一种常用的数据结构,它表示一组唯一元素的集合。在不同的编程语言和库中,set 可能有不同的实现方式和特性。

set 集合数据结构具有以下特性:

在这里插入图片描述

Go语言中最常用的两种数据结构分别是 slice 和 map。 除了 Go 内置的数据结构,还有一些数据结构是由 Go 的官方 container 包提供,如 heap 堆、list 双向链表和ring 回环链表。但Go语言中并没有内置set这种数据结构。本文聊聊go语言中set的实现方式。

我们知道 map 的键是具有唯一性,所以可以用 map 来实现数据结构 set。

set的实现

使用map使用一个set集合,意味着我们只关心 key 的存在,其 value 值并不重要,直接将vlaue设置为空接口。

package main

import (
	"errors"
	"fmt"
	"sync"
)

/*
用map实现一个线程安全的set
*/

type void struct{}

var member void

type IData interface{}

type Set struct {
	mapset map[IData]struct{}
	mutex  sync.Mutex
}

func NewSet() *Set {
	return &Set{
		mapset: make(map[IData]struct{}),
		mutex:  sync.Mutex{},
	}
}

func (s *Set) Add(data IData) bool {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	s.mapset[data] = member
	return true
}

func (s *Set) Remove(data IData) error {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	for k, _ := range s.mapset {
		if k == data {
			delete(s.mapset, k)
			return nil
		}
	}
	return errors.New("not found")
}

func (s *Set) Pop() IData {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	if len(s.mapset) <= 0 {
		return nil
	}
	for k, _ := range s.mapset {
		return s.mapset[k]
	}
	return nil
}

func (s *Set) Size() int {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	return len(s.mapset)

}

func (s *Set) All() []IData {
	s.mutex.Lock()
	defer s.mutex.Unlock()
	datas := make([]IData, 0)
	for k, _ := range s.mapset {
		datas = append(datas, k)
	}
	return datas
}

func main() {
	// test
	myset := NewSet()
	myset.Add(1)
	myset.Add(2)
	myset.Add(1)
	fmt.Println(myset.All()) // [1 2]

	myset.Add(3)
	fmt.Println(myset.Size()) //3
	fmt.Println(myset.All())  // [1 2 3]

	myset.Remove(2)
	fmt.Println(myset.All()) // [1 2 3]

}

set的三方库

在kubernetes中也实现了stirng,int32,int43,byte等几种基本类型为值的set集合。接下来我们分析下源码实现。找到源码为位置k8s.io/apimachinery/pkg/util/sets

// sets.String is a set of strings, implemented via map[string]struct{} for minimal memory consumption.
// String类型定义,使用map来实现set集合,集合的元素是string
type String map[string]Empty

// NewString creates a String from a list of values.
// 构造一个set,set集合存放的值是string类型
func NewString(items ...string) String {
	ss := String{}
	ss.Insert(items...)
	return ss
}


// Insert adds items to the set.
// 插入元素到集合
func (s String) Insert(items ...string) String {
	for _, item := range items {
		s[item] = Empty{}
	}
	return s
}

// Delete removes all items from the set.
// 从set中删除指定string
func (s String) Delete(items ...string) String {
	for _, item := range items {
		delete(s, item)
	}
	return s
}

// Has returns true if and only if item is contained in the set.
// 判断set是否包含指定的string
func (s String) Has(item string) bool {
	_, contained := s[item]
	return contained
}

// HasAll returns true if and only if all items are contained in the set.
// 判断set是否包括一组所有的字符串
func (s String) HasAll(items ...string) bool {
	for _, item := range items {
		if !s.Has(item) {
			return false
		}
	}
	return true
}

// HasAny returns true if any items are contained in the set.
// 判断一组字符串是否有包括在set中
func (s String) HasAny(items ...string) bool {
	for _, item := range items {
		if s.Has(item) {
			return true
		}
	}
	return false
}

总结

本文介绍了set的特点,并介绍go语言中如何用map实现一个set,最后我们分析了kubernete源码中的set库的源码。由于源码比较简单,就没有展开分析。

到此这篇关于go语言中数据接口set集合的实现的文章就介绍到这了,更多相关go语言 set集合内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文