Redis
ZADD key score member [[score member] [score member] ...]
将一个或多个 member 元素及其 score 值加入到有序集 key 当中。
如果某个 member 已经是有序集的成员,那么更新这个member 的score 值,并通过重新插入这个member 元素,来保证该member 在正确的位置上。
score 值可以是整数值或双精度浮点数。
如果 key 不存在,则创建一个空的有序集并执行ZADD 操作。
当 key 存在但不是有序集类型时,返回一个错误。
对有序集的更多介绍请参见 sorted set 。
- 可用版本:
- >= 1.2.0
- 时间复杂度:
- O(M*log(N)), N 是有序集的基数, M 为成功添加的新成员的数量。
- 返回值:
-
被成功添加的新成员的数量,不包括那些被更新的、已经存在的成员。
# 添加单个元素 redis> ZADD page_rank 10 google.com (integer) 1 # 添加多个元素 redis> ZADD page_rank 9 baidu.com 8 bing.com (integer) 2 redis> ZRANGE page_rank 0 -1 WITHSCORES 1) "bing.com" 2) "8" 3) "baidu.com" 4) "9" 5) "google.com" 6) "10" # 添加已存在元素,且 score 值不变 redis> ZADD page_rank 10 google.com (integer) 0 redis> ZRANGE page_rank 0 -1 WITHSCORES # 没有改变 1) "bing.com" 2) "8" 3) "baidu.com" 4) "9" 5) "google.com" 6) "10" # 添加已存在元素,但是改变 score 值 redis> ZADD page_rank 6 bing.com (integer) 0 redis> ZRANGE page_rank 0 -1 WITHSCORES # bing.com 元素的 score 值被改变 1) "bing.com" 2) "6" 3) "baidu.com" 4) "9" 5) "google.com" 6) "10"
ZREVRANGE key start stop [WITHSCORES]
返回有序集 key 中,指定区间内的成员。
其中成员的位置按
score 值递减(从大到小)来排列。
具有相同
score 值的成员按字典序的逆序(
reverse lexicographical order)排列。
除了成员按 score 值递减的次序排列这一点外, ZREVRANGE 命令的其他方面和 ZRANGE 命令一样。
- 可用版本:
- >= 1.2.0
- 时间复杂度:
- O(log(N)+M), N 为有序集的基数,而 M 为结果集的基数。
- 返回值:
- 指定区间内,带有 score 值(可选)的有序集成员的列表。
redis> ZRANGE salary 0 -1 WITHSCORES # 递增排列 1) "peter" 2) "3500" 3) "tom" 4) "4000" 5) "jack" 6) "5000" redis> ZREVRANGE salary 0 -1 WITHSCORES # 递减排列 1) "jack" 2) "5000" 3) "tom" 4) "4000" 5) "peter" 6) "3500"
API实战代码(排名的添加和读取):
User(用户类):
package com.duobei.model; import java.io.Serializable; public class User implements Serializable { private static final long serialVersionUID = 1L; private String id; //编号 private String name; //姓名 private double score; //得分 private int rank; //排名 public User() { } public User(String id, String name, double score) { this.id = id; this.name = name; this.score = score; } public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public double getScore() { return score; } public void setScore(double score) { this.score = score; } public int getRank() { return rank; } public void setRank(int rank) { this.rank = rank; } @Override public String toString() { return "User [id=" + id + ", name=" + name + ", score=" + score + ", rank=" + rank + "]"; } }
自定义序列化封装类:
package com.duobei.tools; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; public class ObjectSer { /** * 对象序列化 * @param obj * @return */ public static byte[] ObjectToByte(Object obj) { byte[] bytes = null; try { ByteArrayOutputStream bo = new ByteArrayOutputStream(); ObjectOutputStream oo = new ObjectOutputStream(bo); oo.writeObject(obj); bytes = bo.toByteArray(); bo.close(); oo.close(); } catch(Exception e) { e.printStackTrace(); } return bytes; } /** * 反序列化 * @param bytes * @return */ public static Object ByteToObject(byte[] bytes) { Object object = null; try { ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream ois = new ObjectInputStream(bais); object = ois.readObject(); } catch (Exception e) { e.printStackTrace(); } return object; } }
测试类(添加后读取):
package com.duobei.test; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool; import com.duobei.model.User; import com.duobei.tools.ObjectSer; public class RankingTest { private ApplicationContext context; private ShardedJedisPool shardedJedisPool; private ShardedJedis jedis; public RankingTest() { } @Before public void init() throws Exception { String config[] = { "applicationContext.xml" }; context = new ClassPathXmlApplicationContext(config); shardedJedisPool = (ShardedJedisPool) context.getBean("shardedJedisPool"); jedis = (ShardedJedis) shardedJedisPool.getResource(); } @Test @Ignore public void rankAdd() { User user1 = new User("12345", "常少鹏", 99.9); User user2 = new User("12346", "王卓卓", 99.8); User user3 = new User("12347", "邹雨欣", 96.8); User user4 = new User("12348", "郑伟山", 98.8); User user5 = new User("12349", "李超杰", 99.6); User user6 = new User("12350", "董明明", 99.0); User user7 = new User("12351", "陈国峰", 100.0); User user8 = new User("12352", "楚晓丽", 99.6); jedis.zadd("game".getBytes(), user1.getScore(), ObjectSer.ObjectToByte(user1)); jedis.zadd("game".getBytes(), user2.getScore(), ObjectSer.ObjectToByte(user2)); jedis.zadd("game".getBytes(), user3.getScore(), ObjectSer.ObjectToByte(user3)); jedis.zadd("game".getBytes(), user4.getScore(), ObjectSer.ObjectToByte(user4)); jedis.zadd("game".getBytes(), user5.getScore(), ObjectSer.ObjectToByte(user5)); jedis.zadd("game".getBytes(), user6.getScore(), ObjectSer.ObjectToByte(user6)); jedis.zadd("game".getBytes(), user7.getScore(), ObjectSer.ObjectToByte(user7)); jedis.zadd("game".getBytes(), user8.getScore(), ObjectSer.ObjectToByte(user8)); } @Test //@Ignore public void gameRankShow() { Set<byte[]> set = jedis.zrevrange("game".getBytes(), 0, -1); Iterator<byte[]> iter = set.iterator(); int i = 1; List<User> list = new ArrayList<User>(); while(iter.hasNext()) { User user = (User) ObjectSer.ByteToObject(iter.next()); user.setRank(i++); list.add(user); } for(User user : list) System.out.println(user); } }
测试结果:
User [id=12351, name=陈国峰, score=100.0, rank=1] User [id=12345, name=常少鹏, score=99.9, rank=2] User [id=12346, name=王卓卓, score=99.8, rank=3] User [id=12352, name=楚晓丽, score=99.6, rank=4] User [id=12349, name=李超杰, score=99.6, rank=5] User [id=12350, name=董明明, score=99.0, rank=6] User [id=12348, name=郑伟山, score=98.8, rank=7] User [id=12347, name=邹雨欣, score=96.8, rank=8]
同分一般排名也相同,有兴趣朋友可以在读取的时候使用自定义算法实现。