使用redis中的zset进行金牌、银牌、铜牌的排序操作

通过使用redis中的zset进行金牌、银牌、铜牌的排序操作

简介:
1、 Redis 有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。
2、不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。
3、有序集合的成员是唯一的,但分数(score)却可以重复。
4、集合是通过哈希表实现的。 集合中最大的成员数为 2次方32 - 1 (4294967295, 每个集合可存储40多亿个成员)。Redis的ZSet是有序、且不重复
(很多时候,我们都将redis中的有序集合叫做zsets,这是因为在redis中,有序集合相关的操作指令都是以z开头的)

需求分析:
如果使用zest元素的分数进行天然的排序,则分数score至少包含金牌数、银牌数、铜牌数 三种数据。
在此,使用每三位代表一个数
铜牌 0 – 999
银牌 1000 – 1000 000
金牌 1000 000 –
总数可以存放在小数位,也可进行运算获取
总数 0.000 – 0.999
例如:
拉拉果 11金 13银 15铜 11 013 015 . 039

实现目标在这里插入图片描述

Redis配置文件

@Configuration
public class RedisConfig {
    @Bean
    public RedisTemplate<String,Object> redisTemplate(LettuceConnectionFactory factory){
        RedisTemplate<String,Object> template = new RedisTemplate <>();
        template.setConnectionFactory(factory);

        Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
        ObjectMapper om = new ObjectMapper();
        om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        jackson2JsonRedisSerializer.setObjectMapper(om);

        StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

        // 在使用注解@Bean返回RedisTemplate的时候,同时配置hashKey与hashValue的序列化方式。
        // key采用String的序列化方式
        template.setKeySerializer(stringRedisSerializer);
        // value序列化方式采用jackson
        template.setValueSerializer(jackson2JsonRedisSerializer);

        // hash的key也采用String的序列化方式
        template.setHashKeySerializer(stringRedisSerializer);
        // hash的value序列化方式采用jackson
        template.setHashValueSerializer(jackson2JsonRedisSerializer);
        template.afterPropertiesSet();
        return template;
    }
}

进行数据交换的VO对象

@Data	// lombok的注解	
@AllArgsConstructor
@NoArgsConstructor
public class MedalVO implements Serializable {
    // 国家
    private String country;
    // 金牌数量
    private Integer goldMedal;
    // 银牌数量
    private Integer silverMedal;
    // 铜牌数量
    private Integer copperMedal;
    // 奖牌总量
    private Integer total;
}

service层提供核心操作

  1.  获取所有的列表展示信息List
    
  2.  修改奖牌数量
    
  3.  两个转换方法
       				score分数转MedalVO对象
       				MedalVO对象转score分数
    
@Slf4j
@Service
public class MedalServiceImpl implements MedalService {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Resource(name = "redisTemplate")
    private  ZSetOperations<String, Object> zSet;

    @Override
    public void incrMedal(MedalVO medalVO) {

        Double aDouble = transferToDouble(medalVO);
        log.info("修改分数操作");
        log.info(String.valueOf(aDouble));
        zSet.add("olympic:medal", medalVO.getCountry(), aDouble);
    }


    @Override
    public List<MedalVO> getMedalList() {
        // 初始化信息
        // init();

        Set<ZSetOperations.TypedTuple<Object>> typedTuples = zSet.reverseRangeWithScores("olympic:medal", 0, -1);

        List<MedalVO> list = new ArrayList<>();

        for (ZSetOperations.TypedTuple<Object> typedTuple : typedTuples) {
            MedalVO medalVO = transferToMedalVO((String) typedTuple.getValue(), typedTuple.getScore());
            list.add(medalVO);
        }

        return list;
    }

    /**
     * 单独只是为了初始化一下信息
     */
    private void init(){
        zSet.add("olympic:medal","中国", 51021028.1);
        zSet.add("olympic:medal","美国", 36039037.112);
        zSet.add("olympic:medal","俄罗斯", 24013023.06);
    }

    /**
     * 该方法用于将redis中取出的score进行转化为MedalVO对象
     * @param country 国家名称
     * @param score 奖牌信息
     * @return Medal对象
     */
    private MedalVO transferToMedalVO(String country, Double score) {

        MedalVO medalVO = new MedalVO();
        medalVO.setCountry(country);
        medalVO.setGoldMedal((int) (score / 1000000));
        medalVO.setSilverMedal((int) (score / 1000 % 1000));
        medalVO.setCopperMedal((int) (score % 1000));
        medalVO.setTotal((int) ((score * 1000) % 1000));
        return medalVO;

    }
    
    /**
     * 将页面修改的MedalVO数据转化为Double类型的score
     * @param medalVO 页面数据
     * @return score
     */
    private Double transferToDouble(MedalVO medalVO) {
        double total = medalVO.getGoldMedal() + medalVO.getSilverMedal() + medalVO.getCopperMedal();
        double v = medalVO.getGoldMedal() * 1000000 + (medalVO.getSilverMedal() * 1000) + medalVO.getCopperMedal() + (total / 1000);
        return v;
    }

}

**Controller层**
```java
@Slf4j
@Controller
public class MedalController {

    @Autowired
    private MedalService medalService;

    @GetMapping("getInfo")
    @ResponseBody
    public List<MedalVO> getMedalVOList() {
        return medalService.getMedalList();
    }

    @GetMapping("change")
    @ResponseBody
    public void addMedal(MedalVO medalVO) {
        log.info(medalVO.toString());
        medalService.incrMedal(medalVO);
    }

}

页面实现展示
在这里插入图片描述

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值