golang 固定顺序map

33 篇文章 0 订阅
15 篇文章 0 订阅

前言

golang的map是无序的,但有些业务场景需要有序的map来实现需求

实现原理

用一个切片来记录key的顺序

代码

/*
	Description : 固定顺序map
	Author : ManGe
			2912882908@qq.com
			https://github.com/mangenotwork/gathertool
*/

package gathertool

import (
	"sync"
)

// GDMapApi 固定顺序 Map 接口
type GDMapApi interface {
	Add(key string, value interface{}) *gDMap
	Get(key string) interface{}
	Del(key string) *gDMap
	Len() int
	KeyList() []string
	AddMap(data map[string]interface{}) *gDMap
	Range(f func(k string, v interface{})) *gDMap
	RangeAt(f func(id int, k string, v interface{})) *gDMap
	CheckValue(value interface{}) bool // 检查是否存在某个值
	Reverse() //反序
}

// gDMap 固定顺序map
type gDMap struct {
	mux sync.Mutex
	data map[string]interface{}
	keyList []string
	size int
}

// NewGDMap ues: NewGDMap().Add(k,v)
func NewGDMap() *gDMap {
	return &gDMap{
		data:make(map[string]interface{}),
		keyList: make([]string, 0),
		size: 0,
	}
}

// Add  添加kv
func (m *gDMap) Add(key string, value interface{}) *gDMap {
	m.mux.Lock()
	defer m.mux.Unlock()
	if _,ok := m.data[key]; ok {
		m.data[key] = value
		return m
	}
	m.keyList = append(m.keyList, key)
	m.size ++
	m.data[key] = value
	return m
}

// Get 通过key获取值
func (m *gDMap) Get(key string) interface{} {
	m.mux.Lock()
	defer m.mux.Unlock()
	return m.data[key]
}

// Del 删除指定key的值
func (m *gDMap) Del(key string) *gDMap {
	m.mux.Lock()
	defer m.mux.Unlock()
	if _,ok := m.data[key]; ok {
		delete(m.data, key)
		for i := 0; i < m.size; i++ {
			if m.keyList[i] == key {
				m.keyList = append(m.keyList[:i], m.keyList[i+1:]...)
				m.size --
				return m
			}
		}
	}
	return m
}

// Len map的长度
func (m *gDMap) Len() int {
	return m.size
}

// KeyList 打印map所有的key
func (m *gDMap) KeyList() []string {
	return m.keyList
}

// AddMap 写入map
func (m *gDMap) AddMap(data map[string]interface{}) *gDMap {
	for k,v := range data {
		m.Add(k,v)
	}
	return m
}

// Range 遍历map
func (m *gDMap) Range(f func(k string, v interface{})) *gDMap {
	for i := 0; i < m.size; i++ {
		f(m.keyList[i], m.data[m.keyList[i]])
	}
	return m
}

// Range 遍历map含顺序id
func (m *gDMap) RangeAt(f func(id int, k string, v interface{})) *gDMap {
	for i := 0; i < m.size; i++ {
		f(i, m.keyList[i], m.data[m.keyList[i]])
	}
	return m
}

// CheckValue 查看map是否存在指定的值
func (m *gDMap) CheckValue(value interface{}) bool {
	m.mux.Lock()
	defer m.mux.Unlock()
	for i := 0; i < m.size; i++ {
		if m.data[m.keyList[i]] == value {
			return true
		}
	}
	return false
}

// Reverse map反序
func (m *gDMap) Reverse() {
	for i, j := 0, len(m.keyList)-1; i < j; i, j = i+1, j-1 {
		m.keyList[i], m.keyList[j] = m.keyList[j], m.keyList[i]
	}
}

测试

gd := NewGDMap().Add("a", 1).Add("b", 2).Add("c", 3)

总结

我的开源库 https://github.com/mangenotwork/gathertool 有大量的业务实现方案,感兴趣的可以去看看,可以与我沟通和交流学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值