是否存在与Redis排序集(zset)等效的Java数据结构

是否存在与Redis排序集(zset)等效的Java数据结构,java,data-structures,set,ttl,Java,Data Structures,Set,Ttl,Redis有一个称为排序集的数据结构 该接口大致与SortedMap相同,但按值排序,而不是按键排序。我几乎可以使用SortedSet,但它们似乎假设静态排序值 是否有类似概念的规范化Java实现 我的直接用例是在每个元素上构建一个带有TTL的集合。映射的值是过期时间,我会定期修剪过期的元素。我还可以定期延长到期时间。所以。。。有几件事 首先,决定您将更多地使用哪种访问方式。如果您要执行的HashMap操作(get、put)比访问排序列表更多,那么您最好只使用HashMap并在需要修剪集合时对值

Redis有一个称为排序集的数据结构

该接口大致与SortedMap相同,但按值排序,而不是按键排序。我几乎可以使用SortedSet,但它们似乎假设静态排序值

是否有类似概念的规范化Java实现

我的直接用例是在每个元素上构建一个带有TTL的集合。映射的值是过期时间,我会定期修剪过期的元素。我还可以定期延长到期时间。

所以。。。有几件事

首先,决定您将更多地使用哪种访问方式。如果您要执行的HashMap操作(get、put)比访问排序列表更多,那么您最好只使用HashMap并在需要修剪集合时对值进行排序


至于修剪集合,听起来您只想删除时间小于某个时间戳的值,而不是删除最早的n个项。如果是这种情况,那么最好根据值是否满足条件来过滤HashMap。这可能比尝试先对列表排序然后删除旧条目要快。

因为您需要两个单独的条件,一个在键上,另一个在值上,所以在大量数据上获得最佳性能可能需要两个数据结构。您可以依赖于一个规则集,并分别在由TTL排序的PriorityQueue中插入相同的对象。可以通过在包含附加TTL的对象的字段中写入来缓冲TTL;然后,当删除下一个对象时,检查是否有额外的TTL,如果有,则将其与新的TTL一起放回,并且额外的TTL=0[我建议这样做,因为从优先级队列中删除的成本是O(n)]。这将产生删除下一个对象的O(logn)时间(+由于受碰撞的TTL而产生的成本,这将取决于发生的频率)和插入,以及受碰撞的TTL的O(1)或O(logn)时间,这取决于您选择的集合的实现

当然,最干净的方法是设计一个封装所有这些内容的新类


此外,如果您的数据集不是很大,所有这些都是多余的。

请查看。番石榴也适用于您的用例。

您可以使用两种数据结构的组合来实现它。 键到分数的排序映射。以及分数到关键点的排序反向映射

在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
  }

  ....

}

分类数据集{
TreeMap>keyToScore;
树形图>scoreToKey
公共分类数据集(){
keyToScore=newtreemap();
scoreToKey=新树映射();
}
无效附加项(字符串键,整数分数){
if(keyToScore.contains(key)){
//删除旧密钥和旧分数
}
//向两个地图添加关键点和分数
}
列出getKeysInRange(int StartCore、int endScore){
//遍历scoreToKey并检索所有值
}
....
}

看看java.util.PriorityQueue。它不是一个集合,但它确实保持了元素的有序排列,使修剪变得容易。