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名
说点什么
您将是第一位评论人!