前言:
Redis可以存储键与5种不同数据结构类型之间的映射,这5种数据结构类型分别为String(字符串)、List(列表)、Set(集合)、Hash(散列)和 Zset(有序集合)。
RedisTemplate中定义了对5种数据结构操作
redisTemplate.opsForValue();//操作字符串
redisTemplate.opsForHash();//操作hash
redisTemplate.opsForList();//操作list
redisTemplate.opsForSet();//操作set
redisTemplate.opsForZSet();//操作有序set
一、Redis的数据结构:字符串
字符串类型是Redis中最为基础的数据存储类型, 它将一个键和一个值存储在redis内存中,类似于java中的Map结构,让Redis通过键去找到值。在Redis中是二进制安全的,这便意味着该类型可以接受任何格式的数据。
例如:假设产品的编号为0001,只要设置了key为product_0001,就可以通过product_0001去保存该产品到redis中,也可以通过product_0001从redis中找到该产品的信息。
常用命令:
注意:如果字符串是数字,那么redis还能支持简单运算,但功能十分有限。如要进行运算,一般是在java中获取它,然后通过java进行运算。
二、Redis的数据结构:哈希
redis中哈希结构也类似于Java的Map,一个对象中有许多键值对,它特别适合于存储对象。在Rdis中,hash是一个String类型的field(字段)和value的映射表。
例如角色有两个字段和对象的值,通过hash结构保存后的内存结构如下图:
常用命令:
public class TestHash {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
//加载配置文件
ApplicationContext cxt = new
ClassPathXmlApplicationContext("testhash.xml");
//获得代理对象
RedisTemplate redisTemplate = cxt.getBean(RedisTemplate.class);
Map<String,String> map = new HashMap<String,String>();
map.put("id", "001");
map.put("name", "小东");
//相当于hmset
redisTemplate.opsForHash().putAll("role1", map);
//相当于hset
redisTemplate.opsForHash().put("role1", "age", "20");
//相当于hgetall
Map<String,String> role = redisTemplate.opsForHash().entries("role1");
//{id=001, name=小东, age=20}
System.out.println(role);
//结果:001
System.out.println(role.get("id"));
}
}
三、Redis数据结构:链表(linked-list)
链表结构是Redis中的常用结构,可以存储多个字符串,而且是有序的。
要注意的一点,就是它是双向链表,所以只能从左向右或者从右向左地访问和操作链表里面的数据节点。所以向列表两端添加删除元素的时间复杂度为0(1),获取越接近两端的元素速度就越快。但是遍历查询就很慢了。
因为是双向链表,所以分为左操作和右操作。我们可以通过push,pop操作从链表的头部或者尾部添加删除元素。
//增
redisTemplate.opsForList.leftPushAll("list1",nodeList);
//删,并设置超时时间
redisTemplate.opsForList.leftPop("list1",1,TimeUnit.SECONDS);
四、Redis数据结构:集合Set
Set集合类型提供的是一个列表的功能,而且是可以自动去重的。它的内部实现其实是一个value值为null的HashMap。采用了hash表结构,所以插入、删除和查找的复杂度都是O(1)。集合最大的优势在于可以进行交集并集差集操作。
特点:没有重复元素,无序,每一个元素都是String数据结构类型。
五、Redis数据结构:有序集合
有序集合和集合类似,只是说它是有序的,和无序集合的主要区别在于每一个元素除了值之外,它还会多出来一个分数。分数是一个浮点数,在java中是使用双精度表示的,根据分数,Redis就可以支持对分数从小到大或者从大到小的排序。其他性质与无序集合类似。
有序集合是依赖Key标示它是属于哪个集合,依赖分数进行排序,所以值和分数是必须的,而实际上不仅可以对分数排序,在一定条件下,还可以对值排序。
在Spring中使用Redis的有序集合,需要注意的是Spring对Redis有序集合的元素的值和分数的范围和限制进行了封装。在Spring中有一个接口:TypedTuple,其中有两个方法getValue()获得值,getScore()方法获得分数。在spring-data-redis中提供了TypedTuple的实现类DefaultTypedTuple(value,score)。
Spring不仅对有序集合元素封装,而且对范围也进行了封装。它使用了接口RedisZSetCommands中的内部类Range,通过Range.range()方法生成一个Range对象,它有以下方法:
//设置大于等于min
public Range gte(Object min);
//设置大于min
public Range gt(Object min);
//设置小于等于min
public Range lte(Object max);
//设置小于min
public Range lt(Object max);
public class TestHash {
@SuppressWarnings("unchecked")
public static void main(String[] args) {
//加载配置文件
ApplicationContext cxt = new
ClassPathXmlApplicationContext("testset.xml");
//获得代理对象
RedisTemplate redisTemplate = cxt.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++) {
j--;
Double score1 = Double.valueOf(i);
String value1 = "x" + i;
Double score2 = Double.valueOf(j);
String value2 = j%2==1?"y" + j:"x"+j;
TypedTuple t1 = new DefaultTypedTuple(value1, score1);
set1.add(t1);
TypedTuple t2 = new DefaultTypedTuple(value2, score2);
set2.add(t2);
}
//把元素插入有序集合zset
redisTemplate.opsForZSet().add("zset1", set1);
redisTemplate.opsForZSet().add("zset2", set2);
//统计总数
Long size = null;
size = redisTemplate.opsForZSet().zCard("zset1");
System.out.println(size);
//计分数为score,求3<=score<=6的元素个数
size = redisTemplate.opsForZSet().count("zset1", 3, 6);
System.out.println(size);
//取下标从1到5的元素
Set set = redisTemplate.opsForZSet().range("zset1",1,5);
System.out.println(set);
//取所有元素
Set set11 = redisTemplate.opsForZSet().range("zset1",0,-1);
System.out.println(set11);
}
}
六、基数:HyperLogLog
基数是一种算法。主要用于评估大概需要准备多少个存储单元去存储数据,例如{1,2,3,4,3,2,1}的基数集合为{1、2、3、4},就是去除重复的元素,所有它的基数就是4。
用的不多,了解就好。
图片来源:https://www.cnblogs.com/dijia478/p/8058775.html