ecodeclub / ekit

支持泛型的工具库

Home Page:https://doc.meoying.com/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mapx: MutipleTreeMap

flycash opened this issue · comments

仅限中文

使用场景

在一些场景下,我们需要一个特殊的 map,这个 map 的值是切片。这种在别的框架里面的叫做 MultipleMap,Multiple 指的就是 map 的值不是单一的值,而是一个切片。

基于哪个 Map 来改造

在 ekit 里面有两个 map 的实现,一个是 HashMap,一个是 TreeMap。

理论上来说我们可以为这两个 Map 结构都提供 MutipleMap 的实现。在这种程度下,理论上:

type MultipleMap[K any, V any] struct {
   // 这里是 mapi 的接口
   m mapi[K, []V]
}

这种设计形态意思是对 mapi 进行一个二次封装,来实现 MultipleMap。MultipleMap 会实现 mapi 接口。

注意:任何返回数据的接口,例如说 Get,按照道理来说应该返回值,也就是一个切片,那么这个切片必须是一个副本。也就是说,原本的值是一个切片,你不能直接返回这个切片。因为这个切片会被人篡改掉。

而后暴露两个初始化方法:

func NewMultipleTreeMap[K any, V any](comparator ekit.Comparator) *MultipleMap[K, V] {

}

func NewMultipleHashMap[K Hashable, V any]() *MultipleMap[K, V] {

}

这种设计的好处是:

  • 整体是无侵入式的
  • 后续如果还有 mapi 的实现,这里增加一个初始化方法就可以了。

值是否应该使用集合

在 ekit 里面,值有多种选择。

  • 使用切片
  • 使用 List 结构

目前来说,我认为并没有太大的必要使用 List 结构,切片就足够了。

是否需要允许用户控制切片初始化的容量?

意思是在 Put 方法里面:

vals, ok := m.Get(key)
if !ok {
    vals = make([]V, 0, capacity)
}

这个 capacity 要不要允许用户控制?答案是暂时不需要暴露这个接口。也就是说我们直接无脑 append 就可以了。

这是因为,大部分情况下,值不会有很多元素,我个人用的话是一个元素居多。在元素不多的时候,即便扩容也是极快的。