Mysql有序集合实现的数据结构_Redis数据结构-------有序集合

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 {

public interface TypedTuple extends Comparable> {

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 set1 = new HashSet();

Set set2 = new HashSet();

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

*/

private static void printTypedTuple(Set 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();

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值