java-redis排行榜value+time排序
阿新 • • 發佈:2021-01-09
本文預覽
需求
做一個送花排行榜
- 根據玩家送花數量倒敘排列
- 送花數量相同時,先送花的在前面
思路
用redis存取資料,自動維護有序集合 。
但值一樣時,無法保證誰在前誰在後。所以可以把存入的時間考慮進去。
這樣排序就變成了: 數值 + 時間。
因為送花數量是整數,那能不能把時間變成小數加在後面呢,這樣取資料的時候,直接取整就是原始資料了。
公式:
newValue = value + 1 - time / Math.pow(10, (int) Math.log10(time) + 1d)
value原始資料,time是存入時間毫秒數,newValue存入redis中的資料
newValue整數部分等於value
極值大:value大&time小。
兩個玩家value值一樣,先進榜(time小)的應該在前面。
程式碼
public class RankWithTime { // 玩家類 static class Player { String name; int value; double saveTime; public Player(String name, int value) { this.name = name; this.value = value; } public void setSaveTime(double saveTime) { this.saveTime = saveTime; } public int getValue() { return value; } public String getName() { return name; } @Override public String toString() { return "Player{" + "name='" + name + '\'' + ", value=" + value + ", saveTime=" + saveTime + '}'; } } // 資料儲存部分 啟動類redis作用 static class Redis { private static Redis INSTANCE; private Redis() {} public static Redis getInstance() { if (INSTANCE == null) { INSTANCE = new Redis(); } return INSTANCE; } /** * 假設這是redis中儲存的資料,這裡沒有順序要求 */ private Map<String, Double> dbData = new HashMap<>(); /** * 向redis中存入資料 * 儲存的是經過處理之後的資料 * @param key * @param value */ public long put(String key, int value) { long time = System.currentTimeMillis(); double dValue = value + 1 - time / Math.pow(10, (int) Math.log10(time) + 1d); dbData.put(key, dValue); return time; } /** * 獲取資料 升序 * @return ArrayList */ public List<Map.Entry<String, Double>> getListAsc() { return dbData.entrySet().stream().sorted(Comparator.comparing(Map.Entry::getValue)).collect(Collectors.toList()); } /** * 獲取資料 降序 * @return ArrayList */ public List<Map.Entry<String, Double>> getListDesc() { return dbData.entrySet().stream(). sorted((o1, o2) -> (int) (o2.getValue() - o1.getValue())).collect(Collectors.toList()); } /** * 獲取資料 升序 * @return Map */ public Map<String, Double> getMapAsc() { // HashMap Map<String, Double> hashMap = dbData.entrySet().stream() .sorted((o1, o2) -> (int) (o1.getValue() - o2.getValue())) .collect(Collectors.toMap(o -> o.getKey(), o -> o.getValue(), (oldVal, newVal) -> newVal)); // LinkedHashMap 有序的 Map<String, Double> linkedHashMap = dbData.entrySet() .stream() .sorted((o1, o2) -> (int) (o1.getValue() - o2.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> newVal, LinkedHashMap::new)); return linkedHashMap; } /** * 獲取資料 降序 * @return LinkedHashMap */ public Map<String, Double> getMapDesc() { return dbData.entrySet() .stream() .sorted((o1, o2) -> (int) (o2.getValue() - o1.getValue())) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (oldVal, newVal) -> newVal, LinkedHashMap::new)); } } public static void main(String[] args) { // 建立 redis final Redis redis = Redis.getInstance(); // 值相同 時間不同 結論:時間小的在前 int value = 100; List<Player> players = new ArrayList<>(); players.add(new Player("玩家1", value)); players.add(new Player("玩家2", value + 1)); players.add(new Player("玩家3", value)); // 存資料 players.forEach(player -> { long putTime = redis.put(player.getName(), player.getValue()); player.setSaveTime(putTime); System.out.println("存入資料順序 === " + player); // 延遲 try { Thread.sleep(1L); } catch (InterruptedException e) { e.printStackTrace(); } }); // 取資料 降序 List<Map.Entry<String, Double>> listAsc = redis.getListDesc(); listAsc.forEach(entry -> System.out.println("取出資料順序 === " + new Player(entry.getKey(), entry.getValue().intValue()))); } /* 存入資料順序 === Player{name='玩家1', value=100, saveTime=1.610187990435E12} 存入資料順序 === Player{name='玩家2', value=101, saveTime=1.610187990441E12} 存入資料順序 === Player{name='玩家3', value=100, saveTime=1.610187990442E12} 取出資料順序 === Player{name='玩家2', value=101, saveTime=0.0} 取出資料順序 === Player{name='玩家1', value=100, saveTime=0.0} 取出資料順序 === Player{name='玩家3', value=100, saveTime=0.0} */ }
總結
對照輸出結果來看:
- value不同,value大的在前
- value相同,先來的(time小)在前
完全滿足需要