《Redis应用实例》Java实现(22):排行榜


本例演示如何使用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);
    }
}

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值