通过使用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层提供核心操作
-
获取所有的列表展示信息List
-
修改奖牌数量
-
两个转换方法 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);
}
}
页面实现展示