外贸西班牙语网站建设,wordpress帮助文档,网站建设合理化建议方案,网站虚拟空间多少钱有序集合和集合类似#xff0c;只是说它是有序的#xff0c;和无序集合的主要区别在于每一个元素除了值之外#xff0c;它还会多一个分数。分数是一个浮点数#xff0c;在 Java 中是使用双精度表示的#xff0c;根据分数#xff0c;Redis 就可以支持对分数从小到大或者从…有序集合和集合类似只是说它是有序的和无序集合的主要区别在于每一个元素除了值之外它还会多一个分数。分数是一个浮点数在 Java 中是使用双精度表示的根据分数Redis 就可以支持对分数从小到大或者从大到小的排序。
这里和无序集合一样对于每一个元素都是唯一的但是对于不同元素而言它的分数可以一样。元素也是 String 数据类型也是一种基于 hash 的存储结构。
集合是通过哈希表实现的所以添加、删除、查找的复杂度都是 01。集合中最大的成员数为 2 的 32 次方减 140 多亿个成员有序集合的数据结构如图所示。
有序集合是依赖 key 标示它是属于哪个集合依赖分数进行排序所以值和分数是必须的而实际上不仅可以对分数进行排序在满足一定的条件下也可以对值进行排序。
Redis基础命令
有序集合和无序集合的命令是接近的只是在这些命令的基础上会增加对于排序的操作这些是我们在使用的时候需要注意的细节。
下面讲解这些常用的有序集合的部分命令。有些时候 Redis 借助数据区间的表示方法来表示包含或者不包含比如在数学的区间表示中[2,5] 表示包含 2但是不包含 5 的区间。
Redis有序集合的部分命令
在对有序集合、下标、区间的表示方法进行操作的时候需要十分小心命令注意它是操作分数还是值稍有不慎就会出现问题。
这里命令比较多也有些命令比较难使用在使用的时候务必要小心不过好在我们使用 zset 的频率并不是太高下面是测试结果——有序集合命令展示。 spring-data-redis对有序集合的封装
在 Spring 中使用 Redis 的有序集合需要注意的是 Spring 对 Redis 有序集合的元素的值和分数的范围Range和限制Limit进行了封装在演示如何使用 Spring 操作有序集合前要进一步了解它的封装。
先介绍一个主要的接口——TypedTuple它不是一个普通的接口而一个内部接口它是 org.springframework.data.redis.core.ZSetOperations 接口的内部接口它定义了两个方法代码如下所示。
public interface ZSetOperationsK,V{......
public interface TypedTupleV extends ComparableTypedTupleV {V getValue();Double getScore();
}
......
}这里的 getValue() 是获取值而 getScore() 是获取分数但是它只是一个接口而不是一个实现类。spring-data-redis 提供了一个默认的实现类—— DefaultTypedTuple同样它会实现 TypedTuple 接口在默认的情况下 Spring 就会把带有分数的有序集合的值和分数封装到这个类中这样就可以通过这个类对象读取对应的值和分数了。
Spring 不仅对有序集合元素封装而且对范围也进行了封装方便使用。它是使用接口 org.springframework.data.redis.connection.RedisZSetCommands 下的内部类 Range 进行封装的它有一个静态的 range() 方法使用它就可以生成一个 Range 对象了只是要清楚 Range 对象的几个方法才行为此我们来看看下面的伪代码。
//设置大于等于min
public Range gte(Object min)
//设置大于min
public Range gt(Object min)
//设置小于等于max
public Range lte(Object max)
//设置小于max
public Range lt(Object max)这 4 个方法就是最常用的范围方法。下面讨论一下限制它是接口 org.springframework.data.redis.connection.RedisZSetCommands 下的内部类它是一个简单的 POJO它存在两个属性它们的 getter 和 setter 方法如下面的代码所示。
// ......
public interface RedisZSetCommands {// ......
public class Limit {int offset;int count;
//setter和getter方法
}
//......
}通过属性的名称很容易知道offset 代表从第几个开始截取而 count 代表限制返回的总数量。
通过 Spring 操作有序集合
我们讨论了 spring-data-redis 项目对有序集合的封装。在测试代码前要把 RedisTemplate 的 keySerializer 和 valueSerializer 属性都修改为字符串序列化器 StringRedisSerializer测试代码如下所示。
public static void testZset() {ApplicationContext applicationContext new ClassPathXmlApplicationContext(applicationContext.xml);RedisTemplate redisTemplate applicationContext.getBean(RedisTemplate.class);// Spring提供接口 TypedTuple操作有序集合SetTypedTuple set1 new HashSetTypedTuple();SetTypedTuple set2 new HashSetTypedTuple();int j 9;for (int i 1; i 9; i) {j--;// 计算分数和值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--DefaultTypedTupleTypedTuple typedTuple1 new DefaultTypedTuple(value1, score1);set1.add(typedTuple1);TypedTuple typedTuple2 new DefaultTypedTuple(value2, score2);set2.add(typedTuple2);}// 将元素插入有序集合zset1redisTemplate.opsForZSet().add(zset1, set1);redisTemplate.opsForZSet().add(zset2, set2);// 统计总数Long size null;size redisTemplate.opsForZSet().zCard(set1);// 计分数为score那么下面的方法就是求 3score6的元素size redisTemplate.opsForZSet().count(zset1, 3, 6);Set set null;// 从下标一开始截取5个元素但是不返回分数每一个元索是Stringset redisTemplate.opsForZSet().range(zset1, 1, 5);printSet(set);// 截取集合所有元素并且对集合按分数排序并返回分数每一个元素是TypedTupleset redisTemplate.opsForZSet().rangeWithScores(zset1, 0, -1);printTypedTuple(set);// 将zset1和zset2两个集合的交集放入集合inter_zsetsize 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(xl); // 大于等于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返回1Long 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);// 给集合中的一个元素的分数加上11Double dbl redisTemplate.opsForZSet().incrementScore(zset1, x1,11);redisTemplate.opsForZSet().removeRangeByScore(zset1, 1, 2);set redisTemplate.opsForZSet().reverseRangeWithScores(zset2, 1, 10);printTypedTuple(set);
}/**
* 打印TypedTuple集合
* param set
* -- SetTypedTuple
*/
public static void printTypedTuple(SetTypedTuple 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();
}上面的代码演示了大部分 Spring 对有序集合的操作并给出了比较清晰的注释大家认真思考之后就能熟悉如何通过 Spring 操作有序集合了。