簡體   English   中英

是否有等效於 Redis 排序集 (zset) 的 Java 數據結構

[英]Is there a Java data structure equivalent to Redis sorted sets (zset)

Redis 有一種數據結構,稱為有序集。

接口大致是 SortedMap 的接口,但按值而不是鍵排序。 我幾乎可以使用 SortedSet,但它們似乎假定靜態排序值。

是否有類似概念的規范 Java 實現?

我的直接用例是在每個元素上構建一個帶有 TTL 的集合。 地圖的值將是過期時間,我會定期修剪過期元素。 我還可以定期調整到期時間。

所以……有幾件事。

首先,確定您將更多地使用哪種訪問。 如果您將執行更多 HashMap 操作(獲取、放置)而不是訪問排序列表,那么您最好只使用 HashMap 並在您想要修剪集合時對值進行排序。

至於修剪集合,聽起來您只想刪除時間小於某個時間戳的值,而不是刪除最早的 n 個項目。 如果是這種情況,那么您最好僅根據值是否滿足條件來過濾 HashMap。 這可能比嘗試先對列表進行排序然后刪除舊條目要快。

由於您需要兩個獨立的條件,一個在鍵上,另一個在值上,因此在大量數據上的最佳性能可能需要兩種數據結構。 您可以依賴常規 Set 並分別在 PriorityQueue 中按 TTL 排序插入相同的對象。 可以通過寫入包含附加 TTL 的對象字段來實現 TTL; 然后,當你移除下一個對象時,你檢查是否有額外的 TTL,如果有,你用這個新的 TTL 和額外的 TTL = 0 把它放回去 [我建議這樣做,因為從 PriorityQueue 中移除的成本是 O( n)]。 這將產生 O(log n) 時間來移除下一個對象(+ 由於碰撞的 TTL 產生的成本,這將取決於它發生的頻率)和插入,以及 O(1) 或 O(log n) 的碰撞時間一個 TTL,取決於您選擇的 Set 的實現。

當然,最簡潔的方法是設計一個封裝所有這些的新類。

此外,如果您的數據集不是很大,那么所有這些都是多余的。

看看ExpiringMap Guava 的緩存也可能適用於您的用例。

您可以使用兩種數據結構的組合來實現它。 鍵到分數的排序映射。 以及分數到鍵的排序反向映射。

在 Java 中,通常這些將使用 TreeMap 實現(如果我們堅持標准的集合框架)。

Redis 使用跳過列表來維護排序,但跳過列表和平衡二叉搜索樹(例如 TreeMap)都用於提供平均 O(log(N)) 訪問。

對於給定的排序集,我們可以將其實現為一個獨立的類,如下所示:

class SortedSet {
  TreeMap<String, Integer>> keyToScore;
  TreeMap<Integer, Set<String>>> scoreToKey

  public SortedSet() {
    keyToScore= new TreeMap<>();
    scoreToKey= new TreeMap<>();
  }

  void addItem(String key, int score) {
    if (keyToScore.contains(key)) {
      // Remove old key and old score
    }
    // Add key and score to both maps 

  }

  List<String> getKeysInRange(int startScore, int endScore) {
     // traverse scoreToKey and retrieve all values
  }

  ....

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM