Welcome everyone

简易榜单实现

redis 汪明鑫 810浏览 0评论
package pers.wmx.springbootfreemarkerdemo.service;

import java.util.List;

/**
 * @author: wangmingxin03
 * @date: 2020-06-09
 */
public interface TopListService {
    //seasonId 表示赛季
    void saveUserScore(long seasonId, long userId, long score);

    //获取当前赛季榜单
    List<Long> getTopList(long seasonId);
}

 

package pers.wmx.springbootfreemarkerdemo.service.impl;

import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
import org.springframework.stereotype.Service;

import pers.wmx.springbootfreemarkerdemo.service.TopListService;

/**
 * 简单榜单实现
 *
 * @author: wangmingxin03
 * @date: 2020-06-09
 */
@Service
public class TopListServiceImpl implements TopListService {
    //榜单大小 10  即取榜单前十
    private static final Integer TOP_LIST_SIZE = 10;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Override
    public void saveUserScore(long seasonId, long userId, long score) {
        String key = "topList_" + seasonId;
        stringRedisTemplate.opsForZSet().add(key, String.valueOf(userId), score);

        //手动处理zset,避免大key  把积分第11名到最后一名移除,保留前十名
        stringRedisTemplate.opsForZSet().removeRange(key, 0, -TOP_LIST_SIZE - 1);
    }

    @Override
    public List<Long> getTopList(long seasonId) {
        String key = "topList_" + seasonId;
        Set<TypedTuple<String>> tuples = stringRedisTemplate.opsForZSet()
                .reverseRangeByScoreWithScores(key, 0, Double.POSITIVE_INFINITY, 0, TOP_LIST_SIZE);

        return tuples.stream()
                .map(tuple -> Long.parseLong(Objects.requireNonNull(tuple.getValue())))
                .collect(Collectors.toList());
    }
}

 

跑下单测:

package pers.wmx.springbootfreemarkerdemo;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

import lombok.extern.slf4j.Slf4j;
import pers.wmx.springbootfreemarkerdemo.service.TopListService;

/**
 * @author: wangmingxin03
 * @date: 2020-06-09
 */
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class TopListTest {
    @Autowired
    private TopListService topListService;

    @Test
    public void getTopList(){
        //mock数据
        topListService.saveUserScore(1, 1, 10);
        topListService.saveUserScore(1, 2, 9);
        topListService.saveUserScore(1, 3, 240);
        topListService.saveUserScore(1, 4, 240);
        topListService.saveUserScore(1, 5, 999);
        topListService.saveUserScore(1, 6, 1);
        topListService.saveUserScore(1, 7, 5);
        topListService.saveUserScore(1, 8, 110);
        topListService.saveUserScore(1, 9, 240);
        topListService.saveUserScore(1, 10, 36);
        topListService.saveUserScore(1, 11, 24);
        topListService.saveUserScore(1, 12, 19);

        List<Long> topList = topListService.getTopList(1);
        System.out.println(topList);
    }
}

 

输出:

[5, 9, 4, 3, 8, 10, 11, 12, 1, 2]

 

 

【核心方法】

removeRange  移除指定范围的元素

 

对应redis这个命令     ZREMRANGEBYRANK key start stop

移除有序集key中,指定排名(rank)区间内的所有成员。下标参数start和stop都以0为底,0处是分数最小的那个元素。这些索引也可是负数,表示位移从最高分处开始数。例如,-1是分数最高的元素,-2是分数第二高的,依次类推。

 

reverseRangeByScoreWithScores   按照score从大到小排序,取前count名

 

 

 

转载请注明:汪明鑫的个人博客 » 简易榜单实现

喜欢 (0)

说点什么

您将是第一位评论人!

提醒
avatar
wpDiscuz