package rank_util import ( "sync" ) // RankUtil // @description:排行工具类 type RankUtil struct { // maxCount 排行榜最大数量 maxCount int // compar 对比函数 返回含义 -1:ab compar func(a, b interface{}) int // dataList 排行数据 dataList []*Model // dataDict 数据字典 dataDict map[string]*Model // dataLock 数据锁 dataLock sync.RWMutex } // NewRankUtil // @description: 构造排行对象 // parameter: // @mc:最大容量 // @comp:元素比对方法 // return: func NewRankUtil(mc int, comp func(a, b interface{}) int) *RankUtil { result := &RankUtil{ maxCount: mc, compar: comp, dataList: make([]*Model, 0, mc), dataDict: make(map[string]*Model, mc), } return result } // GetMaxCount // @description: 获取排行榜最大数量 // parameter: // @receiver r: // return: // @int: func (r *RankUtil) GetMaxCount() int { return r.maxCount } // GetCount // @description: 获取排行榜当前数量 // parameter: // @receiver r: // return: // @int: func (r *RankUtil) GetCount() int { r.dataLock.RLock() defer r.dataLock.RUnlock() return len(r.dataList) } // IsFull // @description: 判断排行榜是否已经满了 // parameter: // @receiver r: // return: // @bool: func (r *RankUtil) IsFull() bool { r.dataLock.RLock() defer r.dataLock.RUnlock() return len(r.dataList) == r.maxCount } // GetAll // @description: 获取排行榜内容 // parameter: // @receiver r: // return: // @[]*Model: func (r *RankUtil) GetAll() []*Model { r.dataLock.RLock() defer r.dataLock.RUnlock() result := make([]*Model, 0, len(r.dataList)) for _, item := range r.dataList { if item == nil || item.obj == nil { break } result = append(result, item) } return result } // GetRankListBySkip // @description: 获取排行榜内容 // parameter: // @receiver r: // @skip:跳过的数量 // @count:跳过后需要返回的数量 // return: // @[]*Model: func (r *RankUtil) GetRankListBySkip(skip, count int) []*Model { r.dataLock.RLock() defer r.dataLock.RUnlock() result := make([]*Model, 0, count) cn := len(r.dataList) if skip >= cn { return result } for i := 0; i < count; i++ { item := r.dataList[skip+i] if item == nil || item.obj == nil { break } result = append(result, item) } return result } // GetItemForK // @description: 根据key获取对象 // parameter: // @receiver r: // @k:key // return: // @*Model: func (r *RankUtil) GetItemForK(k string) *Model { r.dataLock.RLock() defer r.dataLock.RUnlock() item, _ := r.dataDict[k] return item } // GetItemForRank // @description: 根据排名获取对应对象 // parameter: // @receiver r: // @rank:排名 // return: // @*Model: func (r *RankUtil) GetItemForRank(rank int) *Model { r.dataLock.RLock() defer r.dataLock.RUnlock() if len(r.dataList) < rank { return nil } return r.dataList[rank-1] } // Refresh // @description: 刷新排行榜 // parameter: // @receiver r: // @k:key // @o:排行持有的对象,业务层不应该持有该对象。否则业务层更改内容,会导致排行榜内容被改变 // @isup:变动是否升高 // return: // @changeRank:排行是否变动 // @dm:如果有对象,因为排行变动导致掉出排行榜,则返回该对象,否则返回nil func (r *RankUtil) Refresh(k string, o interface{}, isup bool) (changeRank bool, dm *Model) { r.dataLock.Lock() defer r.dataLock.Unlock() changeRank = false curItem, exists := r.dataDict[k] if isup { if !exists { newRank := len(r.dataList) + 1 curItem = &Model{rank: newRank, key: k, obj: o} // 排行榜未满,必定入榜,则先加入排行榜 if newRank <= r.maxCount { r.dataList = append(r.dataList, curItem) r.dataDict[curItem.key] = curItem changeRank = true _, dm = r.upRank(curItem) } else { changeRank, dm = r.upRank(curItem) } } else { curItem.obj = o changeRank, dm = r.upRank(curItem) } } else { // 如果在排行榜内,从之前往下比较 if exists { curItem.obj = o changeRank = r.downRank(curItem) } else { // 如果不在排行榜内,直接结束 } } return } // Delete // @description: 删除k指定的对象,很耗性能,不建议高频使用 // parameter: // @receiver r: // @k:key // return: // @bool:true:代表key存在排行榜中,并且删除成功 false:其他情况 func (r *RankUtil) Delete(k string) bool { r.dataLock.Lock() defer r.dataLock.Unlock() m, exists := r.dataDict[k] if !exists { return false } //从当前位置向后移动,到最后的时候,删除 for { if m.rank >= len(r.dataList) { break } am := r.dataList[m.rank] r.exchange(m, am) m = am } //最后一个应该是要删除的对象 r.dataList = append(r.dataList[:m.rank-1:r.maxCount], r.dataList[m.rank:]...) delete(r.dataDict, k) return true } // upRank // @description: 排行升高 // parameter: // @receiver r: // @curItem:当前对象 // return: // @changeRank:排行是否变动 // @dm:因排行变动被移除排行的对象 func (r *RankUtil) upRank(curItem *Model) (changeRank bool, dm *Model) { changeRank = false for { // rank=1,排在第一位,下标为0,故这里需要-2为上一位的下标 beforeIndex := curItem.rank - 2 if beforeIndex < 0 { break } beforeItem := r.dataList[beforeIndex] if r.compar(curItem.obj, beforeItem.obj) <= 0 { break } // 交换操作 tdm := r.exchange(curItem, beforeItem) if tdm != nil { dm = tdm } curItem = beforeItem changeRank = true } return } // downRank // @description: 排行降低 // parameter: // @receiver r: // @curItem:当前对象 // return: // @bool: func (r *RankUtil) downRank(curItem *Model) bool { changeRank := false for { // rank=1,排在第一位,下标为0,需要对比rank=2的,下标为1,故这里直接取rank即可 afterIndex := curItem.rank if afterIndex >= len(r.dataList) { break } afterItem := r.dataList[afterIndex] if r.compar(afterItem.obj, curItem.obj) <= 0 { break } // 交换操作 r.exchange(curItem, afterItem) curItem = afterItem changeRank = true } return changeRank } // exchange // @description: 排行对象交换 // parameter: // @receiver r: // @a:对象a // @b:对象b // return: // @delRank:因交换被移除排行榜的对象 func (r *RankUtil) exchange(a, b *Model) (dm *Model) { tempObj := a.obj tempKey := a.key a.obj = b.obj a.key = b.key b.obj = tempObj b.key = tempKey if a.rank > r.maxCount { delete(r.dataDict, a.key) dm = a } else { r.dataDict[a.key] = a } if b.rank > r.maxCount { delete(r.dataDict, b.key) dm = b } else { r.dataDict[b.key] = b } return }