Golang语言本身未实现set,但是实现了map
golang的map是一种无序的键值对的集合,其中键是唯一的
而set是键的不重复的集合,因此可以用map来实现set
由于map是key-value集合,如果使用map来实现set,则不需要关注value的具体类型和值
struct{}是具有零个元素的struct,struct{}的大小为0,不占用空间,因此十分适合作为value使用
Golang是静态强类型语言,对于int8、uint8、int64、uint64、 string基础数据类型的set,均需要实现类似的代码
以int64为例,实现set的基本操作
采用上面的方法实现,会充斥着大量重复代码,对于其它类型如int8,uint8,string等类型,需要单独实现,尽管逻辑基本一致。
在Go 1.18版本之前,我们可以使用反射来避免这个问题,
使用反射在运行时推断具体的类型,虽然有性能上的损耗,但是单次纳秒级别的操作,基本可以忽略不计。
interface{}是没有方法的空接口,所有类型都实现了空接口
通过反射可以从interface获取对象的值和类型
反射在编译时缺少类型检查,比如对于同一个set,先后插入int类型和string类型数据,在编译和运行阶段均不会报错。
使用反射在一定程度上避免了大量的重复代码,但是将set转换为slice还是会存在重复的相似逻辑的代码
并且需要在运行时获取/判断对象的类型和值,存在一定的性能损耗
在Go 1.18版本提供了范型(Generics)的支持,
范型可以在编译期间进行类型检查和类型推断,相对于反射机制而言,性能有所提升
可以看出来,Int64HashSet性能最优,GenericHashSet次之,HashSet性能最差。
从实际使用角度看
对于Go < 1.18版本,使用HashSet即可。如果追求性能的极致,不介意大量重复代码,那还是使用Int64HashSet
对于单次操作的时间在ns级别,对于大部分业务场景,反射带来的性能损耗基本可以忽略,性能的瓶颈并不在这里。
对于Go >= 1.18版本,可以使用GenericHashSet
如果需要实现有序set,则需要链表辅助实现
如果你觉得还可以,点一下Star🌟
Original: https://www.cnblogs.com/amos01/p/16586250.html
Author: Amos01
Title: Golang实现set
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/516217/
转载文章受原作者版权保护。转载请注明原作者出处!