Redis数据结构

Stella981
• 阅读 568

Redis数据结构---------有序集合

  • 有序集合和集合类似,只是说它是有序的,和无序集合的主要区别在于每一个元素除了值之外,它还会多一个分数。分数是一个浮点数,在Java中是 使用双精度表示的,对于每一个元素都是唯一的,但是对于不同元素而言,它的分数可以一样。元素也是String数据类型,也是一种基于hash的存储 结构。集合是通过哈希表实现的,所以添加、删除、查找的复杂度都是O(1)。集合中最大的成员数为2^32 - 1,有序集合的数据结构。有序集合是依赖 key标示它是属于哪个集合,依赖分数进行排序,所以值和分数是必须的,而实际上不仅可以对分数进行排序,在满足一定条件下,也可以对值进行排序。

Reids基础命令

  • 有序集合和无序集合的命令是接近的,只是在这些命令的基础上,会增加对于排序的操作,这些是我们在使用的时候需要注意的细节。下面讲解这些常 用的有序集合的部分命令。有些时候Redis借助数学区间的表示方法来表示包含或者不包含,比如在数学的区间表示中,[2,5]表示包含2,但是不包含 5的区间。

Redis基础命令

    ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————
        命令                                                          说明                                             备注
    zadd key score1 value1 [score1 value2...]            向有序集合的key,增加一个或者多个成员                 如果还不存在对应key,则创建键为key的有序集合                  
    
    zcard key                                            获取有序集合的成员数                                ------------
    
    zcount key min max                                   根据分数返回对应的成员列表                           默认为包含min和max值,采用数学区间表示的方法,如果需要不包含,
                                                                                                           则在分数前面加入"(",注意注意不支持"【"表示。
    zincrby key increment member                         给有序集合成员值为member的分数增加increment          ------------
    
    zinterstore desKey numKeys key1[key2 key3....]       求多个有序集合的交集,并且将结果保存到desKey中         numKeys是一个整数,表示多少个有序集合
    
    zlexcount key min max                                求有序集合key成员值在min和max的范围                   这里范围为key的成员值,Redis借助数学区间的表示方法,"【"表示
                                                                                                            包含该值,"("表示不包含该值
    zrange key start stop [withscores]                   按照分值的大小(从小到大)返回成员,加入start和stop参    这里记集合最大长度为len,则Redis会将集合排序后,形成一个从0到
                                                         数,可以截取某一段返回。如果输入可选项wirhscores,则连    len-1的下标,然后根据start和stop控制的下标(包含start和stop)返回
                                                         内分数返回                                                                                                       
    zrank key menber                                     按从小到大有序集合的排行                              排名第一的为0,第二的为1......
    
    zrangebylex key min max [limit offset count]         根据值的大小,从小到大排序,min为最小值,max为最大值;    这里范围为key的成员值,Redis借助数学区间的表示方法,"["表示包含该值,
                                                         limit选项可选,当Redis求出范围集合后,会生产下标0到n,    "("表示不包含该值。  
                                                         然后根据偏移量offset和限定返回数count,返回对应的成员                                                                                                               
    zrangebyscore key min max [withscores]               根据分数大小,从小到大求取范围,选项withscores和limit    根据分析求取集合的范围。这里默认包含min和max,如果不想包含,则在参数前
    [limit offset coount]                                请参考zrange命令和zrangebylex说明                      加入"("表示不包含该值。
    
    zremrangebyscore key start stop                      根据分数区间进行删除                                     按照socre进行排序,然后排除0到len-1的下标,然后根据start和stop进行删除。
    
    zremrangebyrank key start stop                       按照分数排行从小到大的排序删除,从0开始计算                 -----------------
    
    zremrangebylex key min max                           按照值的分布进行删除                                     ------------------
    
    zrevrange key start stop [withscores]                从大到小的按分数排序,参数请参见zrange                     与zrange相同,只是排序是从大到小
    
    zrevrangebyscore key max min [withscores]            从大到小的按分数排序,参数请参见zrangebyscore             与zrangebyscore相同,只是排序从大到小
    
    zrevrank key member                                  按从大到小的顺序,求元素的排行                            排名第一位0,第二位1.......
    
    zscore key member                                    返回成员的分数值                                         返回成员的分数
    
    zunionstore desKey numKeys key1 [key2 key3 key4...]  求多个有序集合的并集,其中numKeys是有序集合的个数           -------                
    
    ————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

spring-data-redis对有序集合的封装

  • 在Spring中使用Redis的有序集合,需要注意的是Spring对Redis有序集合的元素的值和分数的范围(Range)和限制(Limit)进行了封装,在演示如 何使用Spring操作有序集合前要进一步了解它的封装。

  • 先介绍一个主要的接口----TypedTuple,它不是一个普通的接口,而是一个内部接口它是org.spingframework.data.redis.core.ZSetOperations 接口的内部接口,它定义了两个方法。

    public interface ZSetOperations<K, V> {

    public interface TypedTuple<V> extends Comparable<ZSetOperations.TypedTuple<V>> {
            V getValue();
    
            Double getScore();
        }
        
    

    }

  • 这里getValue()是获取值,而getScore()是获取分数,但是它只是一个接口,而不是一个实现类。spring-data-redis提供了一个默认的实现类-- DefaultTypedTuple,同样它会实现TypeTuple接口,在默认的情况下Spring就会把带有分数的有序集合的值和分数封装到这个类中,这样就可以通 过这个类对象读取对应的值和分数了。

  • Spring不仅对有序集合元素封装,而且对范围也进行了封装,方便使用。它是使用接口org.springframework.data.redis.connection.RedisZ- SetCommands下的内部类Range进行封装的,它有一个静态的range()方法,使用它就可以生成一个Range对象了,只是要清楚Range对象的几个方法 才行。 伪代码:

    //设置大于等于min public Range get(Object min) //设置大于min public Range gt(Object min) //设置小于等于max public Range lte(Object max) //设置小于max public Reange lt(Objectt max)

使用Spring操作有序集合

  • 在测试代码前,要把RedisTemplate的keySerializer和valueSerializer属性都修改为字符串序列化器StringRedisSerializer,然后就可以测 试代码。

通过Spring操作有序集合

    /**
     * 通过Spring操作有序集合
     */
    @Test
    public void testZset() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        RedisTemplate redisTemplate = applicationContext.getBean(RedisTemplate.class);
        //Spring提供接口TypedTuple操作有序集合
        Set<TypedTuple> set1 = new HashSet<TypedTuple>();
        Set<TypedTuple> set2 = new HashSet<TypedTuple>();
        int j = 9;
        for (int i = 1; i <= 9; i++) {
            //计算分数和值
            Double score1 = Double.valueOf(i);
            String value1 = "x" + i;
            Double score2 = Double.valueOf(j);
            String value2 = j % 2 == 1 ? "Y" + j : "X" + j;
            //使用Spring提供的默认TypedTuple----DefaultTypedTuple
            TypedTuple typedTuple1 = new DefaultTypedTuple(value1, score1);
            set1.add(typedTuple1);
            TypedTuple typedTuple2 = new DefaultTypedTuple(value2, score2);
            set2.add(typedTuple2);
        }
        //将元素插入有序集合zset1
        redisTemplate.opsForZSet().add("zset1", set1);
        redisTemplate.opsForZSet().add("zset2", set2);
        //统计总数
        Long size = null;
        size = redisTemplate.opsForZSet().zCard("zset1");
        //计分数为score,那么下面的方法就是求3<= score <=6 的元素
        size = redisTemplate.opsForZSet().count("zset1", 3, 6);
        Set set = null;
        //从下标一开始截取5个元素,但是不返回分数,每一个元素是String
        set = redisTemplate.opsForZSet().range("zset1", 1, 5);
        printSet(set);
        //截取集合所有元素,并且对集合按分数排序,并返回分数,每一个元素是TypedTuple
        set = redisTemplate.opsForZSet().rangeWithScores("zset1", 0, -1);
        printTypedTuple(set);
        //将zset1和zset2两个集合的交集放入集合inter_zset
        size = redisTemplate.opsForZSet().intersectAndStore("zset1", "zset2", "inter_zset");
        //区间
        Range range = Range.range();
        range.lt("x8"); //小于
        range.gt("x1"); //大于
        set = redisTemplate.opsForZSet().rangeByLex("zset1", range);
        printSet(set);
        range.lte("x8"); //小于等于
        range.gte("x1"); //大于等于
        set = redisTemplate.opsForZSet().rangeByLex("zset1", range);
        printSet(set);
        //限制返回个数
        Limit limit = Limit.limit();
        limit.count(4);
        //限制从第五个开始截取
        limit.offset(5);
        //求区间内的元素,并限制返回4条
        set = redisTemplate.opsForZSet().rangeByLex("zset1", range, limit);
        printSet(set);
        //求排行,排名第1返回0,第2返回1
        Long rank = redisTemplate.opsForZSet().rank("zset1", "x4");
        System.err.println("rank = " + rank);
        //删除元素,返回删除个数
        size = redisTemplate.opsForZSet().remove("zset1", "x5", "x6");
        System.err.println("delete = " + size);
        //按照排行删除从0开始算起,这里将删除排名第2和第3的元素
        size = redisTemplate.opsForZSet().removeRange("zset2", 1, 2);
        //获取所有集合的元素和分数,以-1代表全部元素
        set = redisTemplate.opsForZSet().rangeWithScores("zset2", 0, -1);
        printTypedTuple(set);
        //删除指定的元素
        size = redisTemplate.opsForZSet().remove("zset2", "y5", "y3");
        System.err.println(size);
        //给集合中的一个元素的分数加上11
        Double db1 = redisTemplate.opsForZSet().incrementScore("zset1", "x1", 11);
        redisTemplate.opsForZSet().removeRangeByScore("zset1", 1, 2);
        set = redisTemplate.opsForZSet().reverseRangeWithScores("zset2", 1, 10);
        printTypedTuple(set);
    }

    /**
     * 打印TypedTuple集合
     * @param set --Set<TypedTuple>
     */
    private static void printTypedTuple(Set<TypedTuple> set) {
        if (set != null && set.isEmpty())
            return;
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            TypedTuple val = (TypedTuple) iterator.next();
            System.err.print("{value = " + val.getValue() + ", score = " + val.getScore() + "}\n");
        }
    }

    /**
     * 打印普通集合
     * @param set
     */
    public static void printSet(Set set) {
        if (set != null && set.isEmpty())
            return;
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            Object val = iterator.next();
            System.out.print(val+ "\t");
        }
        System.out.println();
    }
点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Stella981 Stella981
3年前
KVM调整cpu和内存
一.修改kvm虚拟机的配置1、virsheditcentos7找到“memory”和“vcpu”标签,将<namecentos7</name<uuid2220a6d1a36a4fbb8523e078b3dfe795</uuid
Stella981 Stella981
3年前
Python之time模块的时间戳、时间字符串格式化与转换
Python处理时间和时间戳的内置模块就有time,和datetime两个,本文先说time模块。关于时间戳的几个概念时间戳,根据1970年1月1日00:00:00开始按秒计算的偏移量。时间元组(struct_time),包含9个元素。 time.struct_time(tm_y
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Stella981 Stella981
3年前
HashMap 的底层实现原理
HashMap是一个用于存储KeyValue键值对的集合,每一个键值对也叫做Entry。这些个Entry分散存储在一个数组当中,这个数组就是HashMap的主干。HashMap数组每一个元素的初始值都是Null。 !(https://oscimg.oschina.net/oscnet/8495d30fe00a2865dd74088d2
Stella981 Stella981
3年前
Redis命令行之Zset
一、Redis之Zset简介1\.有序集合Zset是String类型的有序集合。2\.Zset中每个元素都会关联一个double类型的分数值,redis通过分数值来为集合中所有成员进行从小到大排序。3\.Zset的成员是唯一的,但分数值可以重复。4\.Zset是通过hash表实现的,添加、删除、查找的复杂度都是O(1)。5
Stella981 Stella981
3年前
Redis 有序集合(sorted set)
Redis有序集合(sortedset)Redis有序集合和集合一样也是string类型元素的集合,且不允许重复的成员。不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。有序集合的成员是唯一的,但分数(score)却可以重复。集合是
菜园前端 菜园前端
1年前
什么是集合?
原文链接:什么是集合?集合是一种无序且唯一的数据结构,其中的唯一是指集合中的元素。在ES6中新增了一种数据结构Set就是集合。实现功能new()实例化一个集合add()添加元素delete()删除元素has()判断是否存在元素size()获取集合大小应用场