Redis数据结构总结

Redis 是一款开源的,内存中的数据结构存储系统,它可以用作数据库、缓存和消息代理。Redis 支持多种类型的数据结构,如字符串(String)、哈希(Hashes)、列表(Lists)、集合(Sets)、有序集合(Sorted Sets)、位图(Bitmaps)、HyperLogLogs 和地理空间索引(Geospatial)。这些数据结构提供了丰富的操作,使得 Redis 能够应对各种各样的场景。

在这篇博客中,我们将详细介绍 Redis 的各种数据结构,包括它们的特性、底层实现、常用命令以及应用场景。无论你是 Redis 的新手,还是想深入了解 Redis,这篇博客都将为你提供有价值的信息。让我们开始这次的学习之旅吧!


文章目录

        • 1、Redis数据结构概述
          • 1.1、Redis本质就是哈希表
          • 1.2、Redis的哈希冲突与渐进式rehash
          • 1.3、Redis数据结
        • 2、Redis基本数据类型
          • 2.1、String数据结构简介
          • 2.2、List数据结构简介
          • 2.3、Hash数据结构简介
          • 2.4、Set数据结构简介
          • 2.5、ZSet数据结构简介
          • 2.6、Stream数据结构简介
        • 3、Redis特殊数据类型
          • 3.1、Bitmap位存储
          • 3.2、HyperLogLogs基数统计
          • 3.3、Geospatial地理位置


1、Redis数据结构概述

1.1、Redis本质就是哈希表

Redis 本身是一个键值对数据库,这种键值对的存储方式就是哈希映射(Hashmap)的一种体现,即通过键(Key)来快速查找对应的值(Value)。

  • 一个哈希表,其实就是一个数组,数组的每个元素称为一个哈希桶。也就是说,一个哈希表是由多个哈希桶组成的,每个哈希桶中保存了键值对数据;
  • 不管是键类型还是值类型,哈希桶中的元素保存的都不是值本身,而是指向具体值的指针

如下图中可以看到,哈希桶中的 entry 元素中保存了 ‘*key’ 和 '*value ’ 指针,分别指向了实际的键和值,这样一来,即使值是一个集合,也可以通过 '*value 指针被查找到:

image-20230813014946032

因为这个哈希表保存了所有的键值对,所以,它也叫做全局哈希表。

  • 哈希表的最大好处就是让我们可以用 O(1) 的时间复杂度来快速查找到键值对————我们只需要计算键的哈希值,就可以知道它对应的哈希桶位置,然后就可以访问相应的 Entry元素;
  • 这个查找过程主要依赖于哈希计算,和数据量的多少并没有直接关系。也就是说,不管哈希表里有 10 万个键还是 100 万个键,我们只需要一次计算就能找到相应的键。

也就是说,整个数据库就是一个全局 Hash 表,而 Hash 表的时间复杂度就是 O(1),只需要计算每个键的 Hash 值,就知道对应的 Hash 桶的位置,定位桶里面的 Entry 找到对应数据,这个也是 Redis 快的原因之一。

但是,如果我们只是了解哈希表 O(1) 复杂度和快速查找特性,那么,当我们向 Redis 中写入大量数据之后,就可能发现操作有时候会突然变慢了。原因是哈希表的冲突问题和 rehash 可能带来的操作阻塞。

1.2、Redis的哈希冲突与渐进式rehash

Redis 使用哈希表作为其底层数据结构,哈希冲突是哈希表中常见的问题。当两个或更多的键被哈希函数映射到同一个哈希桶时,就会发生哈希冲突。Redis 通过链地址法来解决哈希冲突,即在每个哈希桶中维护一个链表,所有哈希到同一个桶的键值对都存储在这个链表中。

当哈希表中的元素数量增长到一定程度,或者哈希表中的元素数量减少到一定程度,Redis 会触发哈希表的扩容或收缩,这个过程称为 rehash。为了避免 rehash 过程中一次性复制所有元素导致的长时间阻塞,Redis 使用了一种称为“渐进式 rehash”的策略。

在渐进式 rehash 过程中,Redis 会同时维护新旧两个哈希表,并在每次对哈希表进行操作时,将一部分桶从旧哈希表移动到新哈希表。同时,为了保证查询操作的正确性,Redis 在查询时会同时查找新旧两个哈希表。这样,通过分摊在一段时间内完成 rehash,避免了一次性操作带来的性能问题

1.3、Redis数据结

Redis 中的数据结构有 2 种意思:

  1. Redis 键值对中的值的数据类型,也就是数据的保存形式,其包含 6 种基本类型(String(字符串)、List(列表)、Hash(哈希)、Set(集合)、Sorted Set(有序集合)、Stream(流、Redis5.0引入)),和三种特殊类型(geospatial(地理位置)、Bitmap(位存储)、HyperLogLogs(基数统计))
  2. 数据结构的底层实现:底层数据结构一共有 6 种,分别是简单动态字符串、双向链表、压缩列表、哈希表、跳表和整数数组

image-20230813014209872

从上图可以看出:String 的底层是简单动态字符串;List 的底层是双向链表和压缩链表;Hash 的底层是压缩链表和哈希表;Set 的底层是整数数组和哈希表;Sorted Set 底层压缩链表和跳表。也就是说 String 类型的底层实现只有一种数据结构,也就是简单动态字符串。而 List、Hash、Set 和 Sorted Set这 四种数据类型,都有两种底层实现结构。通常情况下,我们会把这四种类型称为集合类型,它们的特点是一个键对应了一个集合的数据。

Redis 之所以采用不同的数据结构,其实是在性能和内存使用效率之间的平衡。


2、Redis基本数据类型

2.1、String数据结构简介

详细链接:Redis数据结构:String类型全面解析

String 是 Redis 最简单的数据类型,也是最常用的数据类型。它可以包含任何数据,包括字符串、整数或者浮点数。在 Redis 中,字符串的最大长度可以达到 512MB。

应用场景:

  1. 缓存:将查询结果、页面内容等缓存在 Redis 的 String 结构中,提高系统访问速度。
  2. 计数器:Redis String 结构可以将字符串解析为整数进行自增或自减操作,适合做各种计数器。
  3. 分布式锁:利用 Redis String 结构的原子性操作,可以实现分布式锁。

底层结构:

Redis 的 String 类型是二进制安全的,它的底层实际上是一个字节数组,因此 String 类型可以包含任何数据,例如 jpg 图片或者序列化的对象。

常用命令:

  1. SET key value:设置键的值。
  2. GET key:获取键的值。
  3. DEL key:删除键。
  4. INCR key:将键的值增加 1。
  5. DECR key:将键的值减少 1。
  6. APPEND key value:将给定 value 值追加到原值的末尾。
  7. STRLEN key:返回键值的长度。
2.2、List数据结构简介

详细链接:Redis数据结构:List类型全面解析

List 是 Redis 的一种数据类型,它是简单的字符串列表,按插入顺序排序。你可以添加一个元素到头部(左边)或尾部(右边)。在 Redis 中,列表最多可以包含 2^32 - 1 个元素。

应用场景:

  1. 消息队列:可以利用 List 的 push 和 pop 操作,实现生产者消费者模型。
  2. 时间线、动态消息:比如微博的时间线,可以将最新的内容放在 List 的最前面。

底层结构:

Redis List 的底层实现为双向链表和压缩列表两种,当列表中的元素个数较少且每个元素的大小较小的时候,Redis 会选择压缩列表作为底层实现,这样可以更加节省内存。当数据量变大时,Redis 会自动将底层实现从压缩列表切换为双向链表。

常用命令:

  1. LPUSH key value:将一个或多个值插入到列表头部。
  2. RPUSH key value:将一个或多个值插入到列表尾部。
  3. LPOP key:移除并返回列表的第一个元素。
  4. RPOP key:移除并返回列表的最后一个元素。
  5. LRANGE key start stop:返回列表中指定区间内的元素。
  6. LINDEX key index:返回列表中指定位置的元素。
  7. LLEN key:返回列表的长度。
2.3、Hash数据结构简介

详细链接:Redis数据结构:Hash类型全面解析

Hash 是 Redis 的一种数据类型,它是键值对集合。是一个字符串字段和字符串值之间的映射表,其字段和值的最大长度都是 512MB。在 Redis 中,哈希可以存储超过 4 亿个键值对。

应用场景:

  1. 存储对象:Hash 结构可以看作是 String 类型的 field 和 value 的映射表,特别适合用于存储对象。
  2. 数据缓存:可以将数据库中的一条记录映射成一个 Hash 结构,Hash 的每个字段对应记录的每个列。

底层结构:

Redis Hash 的底层实现为压缩列表和哈希表两种,当 Hash 中的元素个数较少且每个元素的大小较小的时候,Redis 会选择压缩列表作为底层实现,这样可以更加节省内存。当数据量变大时,Redis 会自动将底层实现从压缩列表切换为哈希表。

常用命令:

  1. HSET key field value:将哈希表 key 中的字段 field 的值设为 value。
  2. HGET key field:获取存储在哈希表中指定字段的值。
  3. HDEL key field:删除哈希表 key 中的一个或多个指定字段。
  4. HGETALL key:获取在哈希表中指定 key 的所有字段和值。
  5. HLEN key:获取哈希表中字段的数量。
  6. HEXISTS key field:查看哈希表 key 中,指定的字段是否存在。
2.4、Set数据结构简介

详细链接:Redis数据结构:Set类型全面解析

Set 是 Redis 的一种数据类型,它是字符串类型的无序集合。和列表一样,你可以添加、删除、查找元素。但是,它保证每个元素只出现一次。在 Redis 中,集合最多可以包含 2^32 - 1 个元素。

应用场景:

  1. 社交网络中的好友关系、共同好友、二度好友等功能。
  2. 利用集合支持的交集、并集、差集等操作,可以计算共同喜好、全部的喜好、自己独有的喜好等。

底层结构:

Redis Set 的底层实现为整数集合和哈希表两种,当集合中的元素都是整数且元素数量较少时,Redis 会选择整数集合作为底层实现,这样可以更加节省内存。当数据量变大或者集合中的元素不全是整数时,Redis 会自动将底层实现从整数集合切换为哈希表。

常用命令:

  1. SADD key member:将一个或多个成员元素加入到集合中。
  2. SMEMBERS key:返回集合中的所有成员。
  3. SISMEMBER key member:判断 member 元素是否是集合 key 的成员。
  4. SREM key member:移除集合中一个或多个成员元素。
  5. SCARD key:返回集合中的元素的数量。

注意事项:

  1. 集合中的元素是无序的,如果需要获取有序的数据,可以使用 Sorted Set 数据类型。
  2. 集合中的元素不允许重复,如果需要存储重复元素,可以使用 List 数据类型。
2.5、ZSet数据结构简介

详细链接:Redis数据结构:Zset类型全面解析

ZSet(有序集合)是 Redis 的一种数据类型,它在 Set 的基础上增加了一个权重参数 score,使得集合中的元素能够按 score 进行有序排列。在 Redis 中,有序集合的最大成员数是 2^32 - 1。

应用场景:

  1. 排行榜应用:有序集合使得我们能够方便地实现排行榜,比如网站的文章排行、学生成绩排行等。
  2. 带权重的消息队列:可以通过 score 来控制消息的优先级。

底层结构:

Redis ZSet 的底层实现为跳跃列表和哈希表两种,跳跃列表保证了元素的排序和快速的插入性能,哈希表则提供了快速查找的能力。

常用命令:

  1. ZADD key score member:向有序集合添加一个或多个成员,或者更新已存在成员的分数。
  2. ZRANGE key start stop [WITHSCORES]:返回有序集中,指定区间内的成员。
  3. ZREM key member:移除有序集合中的一个或多个成员。
  4. ZCARD key:获取有序集合的成员数。
  5. ZSCORE key member:返回有序集中,成员的分数值。

注意事项:

  1. 有序集合中的元素是唯一的,但分数(score)可以重复。
  2. 插入、删除、查找的时间复杂度都是 O(log(N))。对于获取排名(排行榜)的操作,Redis 有序集合是非常高效的。
2.6、Stream数据结构简介

详细链接:Redis数据结构:Stream类型全面解析

Stream 是 Redis 5.0 版本引入的新特性,它是一种类似于日志系统的数据结构,用于存储多个键值对的列表,每个键值对都会被分配一个自动递增的ID。Stream 主要用于实现消息队列的功能,如 Apache Kafka。

应用场景:

  1. 消息队列:Stream 可以作为生产者消费者模型的一种实现,生产者添加消息到 Stream,消费者从 Stream 中读取消息并处理。
  2. 日志记录:由于 Stream 中的每个元素都有唯一的 ID,并且这个 ID 是自动递增的,因此非常适合用来记录日志。

底层结构:

Redis Stream 的底层实现为一种叫做快速列表(quicklist)的数据结构,这是一种同时包含了压缩列表(ziplist)和双向链表特性的数据结构,既可以利用压缩列表节省内存,又可以利用双向链表在两端进行快速的添加、删除操作。

常用命令:

  1. XADD key ID field value [field value …]:向 Stream 中添加元素。
  2. XRANGE key start end [COUNT count]:获取 Stream 中指定范围的元素。
  3. XREAD [COUNT count] [BLOCK milliseconds] STREAMS key [key …] ID [ID …]:从 Stream 中读取数据。
  4. XDEL key ID [ID …]:从 Stream 中删除指定 ID 的元素。
  5. XLEN key:获取 Stream 中的元素数量。

注意事项:

  1. Stream 是 Redis 中唯一一个可以安全地进行多个写入操作的数据结构,因为每个元素都有一个唯一的、自动递增的 ID。
  2. Stream 中的元素一旦被添加,就不能被修改,只能被删除。

3、Redis特殊数据类型

3.1、Bitmap位存储

Redis 的 Bitmap 是一种特殊的字符串数据结构,它可以用来存储位(bit)数据。每个位可以存储 0 或 1 两种值,因此 Bitmap 可以非常高效地存储大量的布尔值。

Redis 的 Bitmap 数据结构可以用于多种场景,特别是需要高效存储和操作大量布尔值的场景。以下是一些常见的使用场景:

  1. 用户活跃度统计:可以用 Bitmap 来记录用户的登录情况,每个位对应一个用户,位的值表示用户是否登录。通过统计位值为 1 的数量,就可以得到活跃用户的数量。

  2. 功能开关:如果一个系统有很多可开启或关闭的功能,可以用 Bitmap 来存储每个功能的开关状态。

  3. 用户权限管理:可以用 Bitmap 来存储用户的权限信息,每个位对应一个权限,位的值表示用户是否拥有该权限。

  4. 统计和分析:Bitmap 可以用于各种统计和分析任务,例如统计特定条件的用户数量,或者分析用户的行为模式等。

需要注意的是,虽然 Bitmap 可以非常高效地存储大量的布尔值,但是它的索引是基于位的,因此如果需要存储的数据有自己的特定索引(如用户 ID),那么可能需要额外的数据结构来维护这种映射关系。

Bitmap 的主要特点是空间效率极高,因为每个布尔值只占用一个位。此外,Redis 提供了一系列的命令,可以对 Bitmap 进行各种位操作,如设置、获取、统计位值为 1 的数量等。

以下是一些常用的 Bitmap 命令:

  1. SETBIT:设置 Bitmap 中指定位置的位值。

    SETBIT mykey 7 1
    
  2. GETBIT:获取 Bitmap 中指定位置的位值。

    GETBIT mykey 7
    
  3. BITCOUNT:统计 Bitmap 中位值为 1 的数量。

    BITCOUNT mykey
    
  4. BITOP:对一个或多个 Bitmap 进行位操作,如 AND、OR、NOT、XOR 等。

    BITOP AND destkey mykey1 mykey2
    

需要注意的是,虽然 Bitmap 可以非常高效地存储大量的布尔值,但是它的索引是基于位的,因此如果需要存储的数据有自己的特定索引(如用户 ID),那么可能需要额外的数据结构来维护这种映射关系。

3.2、HyperLogLogs基数统计

HyperLogLogs 是 Redis 提供的一种概率型的数据结构,用于估计集合的基数(不重复元素的数量)。HyperLogLogs 的优点是,无论集合中包含多少元素,它只需要使用固定大小的内存(大约 12KB)。

应用场景:

  1. 统计在线用户数:如果需要统计一个网站的独立访客数量,使用传统的 Set 结构可能会消耗大量的内存,而使用 HyperLogLogs 只需要消耗固定大小的内存。
  2. 统计大数据集合的基数:例如统计一亿个用户中,有多少不同的搜索关键词。

常用命令:

  1. PFADD key element [element …]:将指定元素添加到 HyperLogLog 中。
  2. PFCOUNT key [key …]:返回给定 HyperLogLog 的基数估算值。
  3. PFMERGE destkey sourcekey [sourcekey …]:将多个 HyperLogLog 合并为一个 HyperLogLog。

注意事项:

  1. HyperLogLogs 提供的是基数的估计值,而不是精确值,但误差率通常不超过 0.81%。
  2. 一旦一个元素被添加到 HyperLogLog,就不能再被移除。
  3. HyperLogLog 对元素的顺序没有要求,也就是说,无论元素以何种顺序被添加,最后的基数估算值都是一样的。
3.3、Geospatial地理位置

Geospatial(地理空间索引)是 Redis 提供的一种特殊类型的 Sorted Set,用于存储地理位置信息(如经纬度),并能够快速计算出两个地点之间的距离。

应用场景:

  1. 地理位置相关的功能:例如查找附近的人、查找附近的商家等。
  2. 计算两个地点之间的距离。

常用命令:

  1. GEOADD key longitude latitude member [longitude latitude member …]:添加一个或多个地理空间位置到指定的 key 中。
  2. GEODIST key member1 member2 [unit]:计算两个给定位置之间的距离。
  3. GEOHASH key member [member …]:返回一个或多个位置元素的 Geohash 表示。
  4. GEOPOS key member [member …]:返回一个或多个位置元素的经纬度。
  5. GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [COUNT count]:查询指定半径内的地理信息位置。

注意事项:

  1. Geospatial 使用的是地球模型,所以计算出的距离是大圆距离。
  2. Geospatial 的底层实现是 Sorted Set,所以它的一些操作(如添加、删除、查找)的时间复杂度和 Sorted Set 是一样的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/100343.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

C盘扩容遇到的问题(BitLocker解密、)

120G的C盘不知不觉的就满了,忍了好久终于要动手了。 尽管电脑-管理--磁盘管理里可以进行磁盘大小调整,但由于各盘都在用,不能够连续调整,所以选用DiskGenius。 # DiskGenius调整分区大小遇到“您选择的分区不支持无损调整容量” …

LINQ详解(查询表达式)

什么是LINQ? LINQ(语言集成查询)是将查询功能直接集成到C#中。数据查询表示简单的字符串,在编译时不会进行类型检查和IntelliSense(代码补全辅助工具)支持。 在开发中,通常需要对不同类型的数据源了解不同的查询语句,如SQL数据库…

老师们快看过来,这里有使用ChatGPT当助教的方法

最近OpenAI官方博客发布了一篇文章How teachers are using ChatGPT(老师们如何使用ChatGPT),讲的是老师们如何在教学中使用ChatGPT,其中有几个例子挺好的,我转述一下,希望对你有用。 制定教案 第一个例子…

【大数据】Flink 详解(六):源码篇 Ⅰ

Flink 详解(六):源码篇 Ⅰ 55、Flink 作业的提交流程?56、Flink 作业提交分为几种方式?57、Flink JobGraph 是在什么时候生成的?58、那在 JobGraph 提交集群之前都经历哪些过程?59、看你提到 Pi…

Android Aidl跨进程通讯(二)--异常捕获处理

学更好的别人, 做更好的自己。 ——《微卡智享》 本文长度为1623字,预计阅读5分钟 前言 上一篇《Android Aidl跨进程通讯的简单使用》中介绍了跨进程的通讯处理,在进程间的数据通过Aidl实现了交互,项目中经常会遇到Bug&#xff0c…

浅谈为什么磁盘慢会导致Linux负载飙升

先说原因结论 在Linux系统上,load average这个指标基本失去了作用,因为你不知道它代表什么意思,当看到load average很高的时候,你不知道是runnable进程太多还是uninterruptible sleep进程太多,也就无法判断是CPU不够用…

乐理-笔记

乐理笔记整理 1、前言2、认识钢琴键盘及音名3、升降号、还原号4、如何区分同一音名的不同键?5、各类音符时值的关系6、歌曲拍号7、拍号的强弱规律8、歌曲速度(BPM)9、附点音符10、三连音12、唱名与简谱数字13、自然大调(白键&…

JavaScript基础04

JavaScript 基础 文章目录 JavaScript 基础函数声明和调用声明(定义)调用 参数形参和实参 返回值作用域全局作用域局部作用域 匿名函数函数表达式立即执行函数 理解封装的意义,能够通过函数的声明实现逻辑的封装,知道对象数据类型…

QT(9.1)对话框与事件处理

作业: 1. 完善登录框 点击登录按钮后,判断账号(admin)和密码(123456)是否一致,如果匹配失败,则弹出错误对话框,文本内容“账号密码不匹配,是否重新登录”&…

B081-Lucene+ElasticSearch

目录 认识全文检索概念lucene原理全文检索的特点常见的全文检索方案 Lucene创建索引导包分析图代码 搜索索引分析图代码 ElasticSearch认识ElasticSearchES与Kibana的安装及使用说明ES相关概念理解和简单增删改查ES查询DSL查询DSL过滤 分词器IK分词器安装测试分词器 文档映射(字…

大数据组件-Flume集群环境搭建

🥇🥇【大数据学习记录篇】-持续更新中~🥇🥇 个人主页:beixi 本文章收录于专栏(点击传送):【大数据学习】 💓💓持续更新中,感谢各位前辈朋友们支持…

sentinel熔断报java.lang.reflect.UndeclaredThrowableException

背景&#xff1a;内部要进行应用jdk&springboot升级&#xff0c;因此也需要将Spring Cloud Hystrix 替换成alibaba sentinel。 依赖 <dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</a…

Android安卓实战项目(13)---记账APP详细记录每天的收入和支出并且分类统计【生活助手类APP】强烈推荐自己也在用!!!(源码在文末)

Android安卓实战项目&#xff08;13&#xff09;—记账APP详细记录每天的收入和支出并且分类统计【生活助手类APP】强烈推荐自己也在用&#xff01;&#xff01;&#xff01;&#xff08;源码在文末&#x1f415;&#x1f415;&#x1f415;&#xff09; 一.项目运行介绍 B站…

机器学习概念

目录 一、人工智能、机器学习、深度学习的关系 二、什么是深度学习&#xff1f; 2.1 深度学习常用算法 一、人工智能、机器学习、深度学习的关系 人工智能、机器学习和深度学习的关系如下所示。 二、什么是深度学习&#xff1f; 深度学习( DL, Deep Learning) 是机器学习 …

机器学习——聚类算法一

机器学习——聚类算法一 文章目录 前言一、基于numpy实现聚类二、K-Means聚类2.1. 原理2.2. 代码实现2.3. 局限性 三、层次聚类3.1. 原理3.2. 代码实现 四、DBSCAN算法4.1. 原理4.2. 代码实现 五、区别与相同点1. 区别&#xff1a;2. 相同点&#xff1a; 总结 前言 在机器学习…

微机原理 || 第3次测试:第八章-常用接口芯片82558253(测试题+手写解析)

&#xff08;一&#xff09;知识点总结 一直没有学明白8253和8255芯片&#xff0c;觉得后面难&#xff0c;其实看懂后&#xff0c;就是照着表格去对应填写&#xff0c; 知道地址怎么回事就没问题哒~ 相信你&#x1f618; 一、8255芯片&#xff08;不是偷懒&#xff0c;真的就…

百亿级访问量,如何做缓存架构设计

说在前面 在40岁老架构师 尼恩的读者社区(50)中&#xff0c;最近有小伙伴拿到了一线互联网企业如阿里、网易、有赞、希音、百度、网易、滴滴的面试资格&#xff0c;遇到一几个很重要的面试题&#xff1a;&#xff1a; 分布式缓存系统&#xff0c;如何架构&#xff1f;百亿级访…

Android安卓实战项目(12)—关于身体分析,BMI计算,喝水提醒,食物卡路里计算APP【支持中英文切换】生活助手类APP(源码在文末)

Android安卓实战项目&#xff08;12&#xff09;—关于身体分析&#xff0c;BMI计算&#xff0c;喝水提醒&#xff0c;食物卡路里计算APP【支持中英文切换】生活助手类APP&#xff08;源码在文末&#x1f415;&#x1f415;&#x1f415;&#xff09; 一.项目运行介绍 B站演示…

题目有点太简单了,不知道怎么选了

有个公司给了下面一个题目&#xff0c;看了下太简单了&#xff0c;都怕选错了。 后来拿着程序跑了下&#xff0c;就是这个意思嘛。 结论 程序跑出来的结果就是对输入的列表进行倒序排列。 public void testGetPut() throws Exception {List<Integer> numbers List.of(…

安防监控/磁盘阵列存储/视频汇聚平台EasyCVR调用rtsp地址返回的IP不正确是什么原因?

安防监控/云存储/磁盘阵列存储/视频汇聚平台EasyCVR可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有GB28181、RTSP/Onvif、RTMP等&#xff0c;以及厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等&#xff0c;能对外分发RTSP、RT…