本例演示如何使用Redis的有序集合(Sorted Set) 数据结构来实现一个按分数排序的排行榜。
package com.foxbill.redisinaction;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.resps.Tuple;
import java.util.ArrayList;
import java.util.List;
/**
* 排行榜,使用Sorted Set
*/
public class Chapter22 {
static private String KEY_RANK = "Chapter22:rank";
static public void start(Jedis jedis) {
cleanData(jedis);
initData(jedis);
int count=3;
List<PlayerScore> top3 = getTopPlayers(jedis,count);
for (PlayerScore ps : top3) {
System.out.println(ps);
}
removePlayer(jedis,"player:002");
top3 = getTopPlayers(jedis,count);
for (PlayerScore ps : top3) {
System.out.println(ps);
}
}
//清除数据
private static void cleanData(Jedis jedis) {
jedis.del(KEY_RANK);
}
//初始化数据
private static void initData(Jedis jedis) {
// 1. 添加一些玩家和分数
addOrUpdateScore(jedis,"player:001", 1500.5);
addOrUpdateScore(jedis,"player:002", 2300.0);
addOrUpdateScore(jedis,"player:003", 800.0);
addOrUpdateScore(jedis,"player:004", 3100.8);
addOrUpdateScore(jedis,"player:005", 1950.3);
}
//设置分数
private static void addOrUpdateScore(Jedis jedis,String playerId, double score) {
try {
// ZADD key score member
// 如果玩家已存在,则更新分数;如果不存在,则添加新玩家
jedis.zadd(KEY_RANK, score, playerId);
System.out.println("玩家 [" + playerId + "] 的分数已更新为: " + score);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 获取排行榜前 N 名(按分数从高到低)
* @param count 获取前几名
* @return 包含玩家ID和分数的列表
*/
private static List<PlayerScore> getTopPlayers(Jedis jedis,int count) {
List<PlayerScore> topPlayers = new ArrayList<>();
try{
// ZREVRANGEWITHSCORES key start stop
// 从 0 开始,到 count-1 结束,获取前 count 名
List<Tuple> result = jedis.zrevrangeWithScores(KEY_RANK, 0, count - 1);
int rank = 1;
for (Tuple tuple : result) {
topPlayers.add(new PlayerScore(rank++, tuple.getElement(), tuple.getScore()));
}
} catch (Exception e) {
e.printStackTrace();
}
return topPlayers;
}
/**
* 从排行榜中移除玩家
* @param playerId 玩家ID
* @return 是否成功移除
*/
private static boolean removePlayer(Jedis jedis,String playerId) {
try{
// ZREM key member
long removed = jedis.zrem(KEY_RANK, playerId);
if(removed == 1){
System.out.printf("已删除玩家%s\n",playerId);
}
return removed > 0;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
}
// 玩家分数数据类
class PlayerScore {
private final int rank;
private final String playerId;
private final double score;
public PlayerScore(int rank, String playerId, double score) {
this.rank = rank;
this.playerId = playerId;
this.score = score;
}
// Getters
public int getRank() { return rank; }
public String getPlayerId() { return playerId; }
public double getScore() { return score; }
@Override
public String toString() {
return String.format("第%d名 - 玩家: %s, 分数: %.1f", rank, playerId, score);
}
}

被折叠的 条评论
为什么被折叠?



