【Redis学习2】Redis常用数据结构与应用场景

news2024/9/22 4:11:40

Redis常用数据结构与应用场景

redis中存储数据是以key-value键值对的方式去存储的,其中key为string字符类型,value的数据类型可以是string(字符串)、list(列表)、hash(字典)、set(集合) 、 zset(有序集合)。 这5种数据类型在开发中可以应对大部分场景的存储
在这里插入图片描述

拓展:key的底层存储方式SDS

这里有一个问题,当我们使用一条redis命令set key value的时候,redis进行了什么操作?
其实当我们使用命令操作redis的时候,也是会经过redis客户端到redis服务端的过程,这些命令相当于一个请求

  • redis客户端通过socket传输这些命令
  • redis服务端通过io读取到这些请求命令,把所有的命令解析成一个字符串,并执行对应命令操作,然后再经过socket写回操作结果!

同时redis是使用c语言写的,但它底层在存放redis的key时,并没有用c语言原生的字符串数据结构,而是定义了一个属于redis的数据结构SDS(Simple Dynamic String),

struct sdshdr{
     //记录buf数组中已使用字节的数量
     //等于 SDS 保存字符串的长度
     int len;
     //记录 buf 数组中未使用字节的数量
     int free;
     //字节数组,用于保存字符串
     char buf[];
}

为什么要用这样的一个数据结构去存储字符串呢?

  • 二进制安全的数据结构。 比如是操作命令是get aaa\0 :获取 aaa\0的值。如果是c语言的字符数组就会把\0吞掉,变为get aaa,而使用SDS就会完整的操作aaa\0SDS把所有接受到的数据都转成字符串,即使是一些特殊字符!
  • SDS提供了内存预分配机制,避免频繁的内存分配。 如果是c语言,在修改一个key时,会分配一个新的字符数组,然后进行内存赋值,而SDS则采用预先分配机制,直接把字符串容量扩大两倍,key的长度变化时,直接在已分配的内存中修改即可,如果不够继续扩大2倍
    思考:SDS采用的也是一种空间换时间的思路,无论是扩展之后分配多余空间从而降低下次扩展时需要再次内存分配的概率,还是缩容之后并不立即回收空间而是留给下次扩容,这两种操作都会导致空闲空间增大,内存占用提升,而Redis又了很多数据压缩策略来控制内存。
  • 杜绝缓冲区溢出。 在C语言原生的字符串中,当需要修改字符串且修改后的长度大于修改前的长度时,在修改之前需要先对原数组申请空间扩容,否则可能导致数组溢出,内容写入到相邻的下一个数组中从而改变下一个字符串的值。
    在SDS中,SDS屏蔽了用户对数组空间的分配,SDS在增长之前会根据free属性自动检测是否足够修改之后的字符串所需空间,如果足够则直接修改,并更新修改之后的len和free属性,如果当前剩余空间不够,SDS会根据空间分配策略自动进行扩容,无需用户关心。
    思考:类似于Java中的String类,高级容器等,会提供自动扩容,缩容的功能,具体的细节对使用者透明,能减少开发者的编码负担。

string+应用场景

常用操作

命令说明
SET key value存入字符串键值对
MSET key value [key value …]批量存储字符串键值对
SETNX key value存入一个不存在的字符串键值对
GET key获取一个字符串键值
MGET key [key …]批量获取字符串键值
EXPIRE key seconds设置一个键的过期时间(秒)
DEL key [key …]删除一个键
INCR key将key中储存的数字值加1
DECR key将key中储存的数字值减1
INCRBY key increment将key所储存的值加上increment
DECRBY key decrement将key所储存的值减去decrement
  • 设置和获取键值对
> SET key value
OK
> GET key
"value"

值得注意的是, 当key存在时,set命令会覆盖掉你上一次设置的值

> SET key newValue
OK
> GET key
"newValue"
  • 使用 EXISTSDEL 关键字来查询是否存在和删除键值对:
> EXISTS key
(integer) 1
> DEL key
(integer) 1
> GET key
(nil)
  • 批量设置键值对
> SET key1 value1
OK
> SET key2 value2
OK
> MGET key1 key2 key3    # 返回一个列表
1) "value1"
2) "value2"
3) (nil)
> MSET key1 value1 key2 value2
> MGET key1 key2
1) "value1"
2) "value2"
  • 过期和 SET 命令扩展
    可以对 key 设置过期时间,到时间会被自动删除,这个功能常用来控制缓存的失效时间。(过期可以是任意数据结构)
> SET key value1
> GET key
"value1"
> EXPIRE name 5    # 5s 后过期
...                # 等待 5s
> GET key
(nil)
  • 返回原值的 GETSET 命令
    对字符串,还有一个 GETSET 比较让人觉得有意思,它的功能跟它名字一样:为 key 设置一个值并返回原值:
> SET key value
> GETSET key value1
"value"

这可以对于某一些需要隔一段时间就统计的 key 很方便的设置和查看,例如:系统每当由用户进入的时候你就是用 INCR 命令操作一个 key,当需要统计时候你就把这个 key 使用 GETSET 命令重新赋值为 0,这样就达到了统计的目的。

使用场景

  • 单值缓存
SET key value
GET key

使用这两条命令可以做用户id存储、商品库存存储等等!

  • 对象存储
    以缓存user对象为例,有以下两种方式:
    (1)SET user:1 value(json格式数据):把对象转json存入redis,也是当下常用的方式,获取数据需要做数据转换
    (2)MSET user:1:name zhuge user:1:balance 1888
    MGET user:1:name user:1:balance
    使用Mset命令,把对象拆开存储,每一个key只保存对象的一个字段信息,适用于经常修改user的某个字段的场景
  • 分布式锁
SETNX product:10001 true //操作product:10001
##执行业务操作...
DEL product:10001 //删除product:10001

其中SETNX key value 命令要求如果key已存在,则其他的setnx命令无法对当前key进行操作。

在使用分布式锁时通常还会通过
SET product:10001 true ex 10 nx 命令设置key的超时时间,防止死锁!

  • 计数器
NCR 文章id

可以使用INCR命令实现数量自增,可以用于文章阅读量、热度人数统计等,用户每点进去一次执行一次INCR命令

  • 分布式系统全局序列号
    在分布式系统下,如果需要分库分表, mysql的数据库自增id已经无法满足分库分表下的id自增,这时就需要一个独立于数据库之外的中间件来实现id的分配。

redis的INCR命令可以实现id、序列号的生成,但如果用户量非常大,每生成一个id、序列号都去redis会给redis添加不小的压力,我们可以一次性从redis中自增1000次,把序列号放入本地内存中,这1000个id用完了,再去redis再取1000个,可有效降低redis的压力!

hash+应用场景

Redis 中的字典(hash)相当于 Java 中的 HashMap,内部实现也差不多类似,都是通过 “数组 + 链表” 的链地址法来解决部分 哈希冲突,同时这样的结构也吸收了两种不同数据结构的优点。

常用操作

命令说明
HSET key field value存储一个哈希表key的键值
HGET key field获取哈希表key对应的field键值
HMSET key field value [field value …]在一个哈希表key中存储多个键值对
HMGET key field [field …]批量获取哈希表key中多个field键值
HSETNX key field value存储一个不存在的哈希表key的键值
HDEL key field [field …]删除哈希表key中的field键值
HLEN key返回哈希表key中field的数量
HGETALL key返回哈希表key中所有的键值
HINCRBY key field increment为哈希表key中field键的值加上增量increment

字典相关操作

> HSET books java "think in java"    # 命令行的字符串如果包含空格则需要使用引号包裹
(integer) 1
> HSET books python "python cookbook"
(integer) 1
> HGETALL books    # key 和 value 间隔出现
1) "java"
2) "think in java"
3) "python"
4) "python cookbook"
> HGET books java
"think in java"
> HSET books java "head first java"  
(integer) 0        # 因为是更新操作,所以返回 0
> HMSET books java "effetive  java" python "learning python"    # 批量操作
OK

使用场景

  • 电商购物车
    1)以用户id为key === cart:1001
    2)以商品id为field===10088
    3)商品数量为value === 1
    因此,购物车操作可以如下:
    1)添加商品:hset cart:1001 10088 1
    2)增加数量 hincrby cart:1001 10088 1
    3)商品总数 hlen cart:1001
    4)删除商品 hdel cart:1001 10088
    5)获取购物车所有商品 hgetall cart:1001
    在这里插入图片描述

思考-优点:
1)同类数据归类整合储存,方便数据管理
2)相比string操作消耗内存与cpu更小
因为:string类型通过set key - val 的方式存储数据,通过对key进行hash运算决定当前key是存储在数组哪个位置。如果把hash类型的数据变成string类型来存储,则需要更多的key,同时在存放时也需要更多的hash(key)运算,消耗更多的cpu资源!
3)相比string储存更节省空间
如果把hash类型的数据变成string类型来存储,将需要存储更多key,如果数据量很多的情况下,redis底层那么存储数据的数组将很快会被占满,占满就会进行扩容,加大内存消耗。由此可见,string结构与hash结构只存储一个key相比,需要更多的内存空间!
思考-缺点:
1)过期功能不能使用在field上,只能用在key上
redis的过期时间只能用在key上,而hash的key是一个大的概念,里面的map型结构才是重要数据,但过期时间只能用在外边的大key上,hash结构相比于string不能实现精准过期!
2)hash结构在Redis集群架构下不适合大规模使用
因为如果一个hash的key中的属性很多的话,只能存在一个redis节点上,那么这个节点压力会比其他节点压力大很多,造成redis集群下压力分配不均衡!

list+应用场景

Redis 的列表相当于 Java 语言中的 LinkedList,注意它是链表而不是数组。这意味着 list 的插入和删除操作非常快,时间复杂度为 O(1),但是索引定位很慢,时间复杂度为 O(n)。

常用操作

命令说明
LPUSH key value [value …]将一个或多个值value插入到key列表的表头(最左边)
RPUSH key value [value …]将一个或多个值value插入到key列表的表尾(最右边)
LPOP key移除并返回key列表的头元素
RPOP key移除并返回key列表的尾元素
LRANGE key start stop返回列表key中指定区间内的元素,区间以偏移量start和stop指定
BLPOP key [key …] timeout从key列表表头弹出一个元素,若列表中没有元素,阻塞等待
timeout:秒,如果timeout=0,一直阻塞等待
BRPOP key [key …] timeout从key列表表尾弹出一个元素,若列表中没有元素,阻塞等待
timeout:秒,如果timeout=0,一直阻塞等待

list相关

  • LPUSHRPUSH分别可以向list的左边(头部)和右边(尾部)添加一个新元素
  • LRANGE命令可以从list中取出一定范围的元素
  • LINDEX命令可以从list中取出指定下标的元素,相当于java量表操作中的get(int index)操作
> rpush mylist A
(integer) 1
> rpush mylist B
(integer) 2
> lpush mylist first
(integer) 3
> lrange mylist 0 -1    # -1 表示倒数第一个元素, 这里表示从第一个元素到最后一个元素,即所有
1) "first"
2) "A"
3) "B"
  • list 实现队列
    队列是先进先出的数据结构,常用于消息排队和异步逻辑处理,它会确保元素的访问顺序:
> RPUSH books python java golang
(integer) 3
> LPOP books
"python"
> LPOP books
"java"
> LPOP books
"golang"
> LPOP books
(nil)
  • list 实现栈
    栈是先进后出的数据结构,跟队列正好相反
> RPUSH books python java golang
> RPOP books
"golang"
> RPOP books
"java"
> RPOP books
"python"
> RPOP books
(nil)

list的使用场景

  • 模拟分布式系统数据结构
    ①:Stack(栈) = LPUSH(左边放) + LPOP(左边取)
    ②:Queue(队列)= LPUSH(左边放) + RPOP(右边取)
    ③:Blocking MQ(阻塞队列)= LPUSH(左边放) + BRPOP(右边阻塞取:没有数据就阻塞!)
    思考:那么redis实现的数据结构和jdk中提供的数据结构有什么区别呢?
    答:jdk提供的数据结构仅在本服务中有用,如果在分布式环境下,则需要借助redis等中间件,模拟数据结构来统一管理数据。
  • 微博、朋友圈、公众号等,关注的文章列表展示
    假如 小明 关注了 中国青年报、三太子敖丙 等大V的订阅号,当这些大V发布订阅号时,通过推或拉的方式把消息LPUSH放入redis中属于小明的list中。其中key为msg:{小明_ID}。当小明要获取大V们发的消息时,使用LRANGE 命令从队列中获取指定个数的订阅号信息!!
# ①:MacTalk发微博,消息ID为10010
LPUSH msg:{小明_ID} 10010

# ②:备胎说车发微博,消息ID为10086
LPUSH msg:{小明_ID} 10086

# ③:查看最新微博消息(前4条)
LRANGE msg:{小明_ID} 0 4

思考:大V发了消息的是怎么存储在粉丝的redis中呢?一般有两种处理方案!
(1)推送,博主发了消息,通过线程先推送到在线粉丝的队列中,其他不在线的粉丝等后面系统在空闲的时候再慢慢推送过去
(2)拉取,如果粉丝太多,推的方案还是要很长时间去处理,还有一种方案就是拉,每一个粉丝上线后就去关注的博主那里拉取他发送的最新的消息,在使用LRANGE取出即可。

set+应用场景

Redis 的集合相当于 Java 语言中的 HashSet,它内部的键值对是无序、唯一的。它的内部实现相当于一个特殊的字典,字典中所有的 value 都是一个值 NULL。

set 的常用操作

命令说明
SADD key member [member …]往集合key中存入元素,元素存在则忽略,若key不存在则新建
SREM key member [member …]从集合key中删除元素
SMEMBERS key获取集合key中所有元素
SCARD key获取集合key的元素个数
SISMEMBER key member判断member元素是否存在于集合key中
SRANDMEMBER key [count]从集合key中选出count个元素,元素不从key中删除
SPOP key [count]从集合key中选出count个元素,元素从key中删除

set 的运算操作

命令说明
SINTER key [key …]交集运算
SINTERSTORE destination key [key …]将交集结果存入新集合destination中
SUNION key [key …]并集运算
SUNIONSTORE destination key [key …]将并集结果存入新集合destination中
SDIFF key [key …]差集运算
SDIFFSTORE destination key [key …]SDIFFSTORE destination key [key …]

集合set的基本使用

> SADD books java
(integer) 1
> SADD books java    # 重复
(integer) 0
> SADD books python golang
(integer) 2
> SMEMBERS books    # 注意顺序,set 是无序的
1) "java"
2) "python"
3) "golang"
> SISMEMBER books java    # 查询某个 value 是否存在,相当于 contains
(integer) 1
> SCARD books    # 获取长度
(integer) 3
> SPOP books     # 弹出一个
"java"

set的使用场景

  • 抽奖活动
    1)点击参与抽奖加入集合
    SADD key {userlD}
    2)查看参与抽奖所有用户
    SMEMBERS key
    3)随机抽取count名中奖者
    SRANDMEMBER key [count] ------元素不从集合中删除
    SPOP key [count] ------ 元素从集合中删除
  • 朋友圈点赞
    当某人在朋友圈发布消息,可用set来点赞展示
    在这里插入图片描述
    1)点赞
    SADD like:{消息ID} {用户ID}
    2)取消点赞
    SREM like:{消息ID} {用户ID}
    3)检查用户是否点过赞
    SISMEMBER like:{消息ID} {用户ID}
    4)获取点赞的用户列表
    SMEMBERS like:{消息ID}
    5)获取点赞用户数
    SCARD like:{消息ID}
  • 利用set的交、并、差集实现微博、微信关注模型
    关注模型如下图:

首先了解一下set的集合操作,假如有三个集合
set1:(a、b、c)
set2:(b、c、d)
set3:(c、d、e)

三个集合的
交集为:SINTER set1 set2 set3 ==> { c }
并集为:SUNION set1 set2 set3 ==> { a,b,c,d,e }
差集为:SDIFF set1 set2 set3 ==> { a }
差集计算方式:set1 - (set2并set3) = {a、b、c} - {b、c、d、e} = {a} 只保留a中单独存在的元素

共同关注A的人:可以用交集来实现
我可能认识的人:可以使用差集来实现,把我的好友求差集,例如a的好友={b,c},b的好友={a,c,d},那么a可能认识的人可以是,b-a={a,b,c,d}-{a,b,c} = {d}。当然这只是一个简单又不大现实的想法,相当于把对方的好友全部推荐给你了,真实情况的还需要考虑到关系网络,好友的权重数等

zset+应用场景

这可能使 Redis 最具特色的一个数据结构了,它类似于 Java 中 SortedSet 和 HashMap 的结合体,一方面它是一个 set,保证了内部 value 的唯一性,另一方面它可以为每个 value 赋予一个 score 值,用来代表排序的权重。
zset相比于set多一个score 分值,正是根据这个分值进行排序,所以zset才能展示有序的数据

zset 的常用操作

命令说明
ZADD key score member [[score member]…]往有序集合key中加入带分值元素
ZREM key member [member …]从有序集合key中删除元素
ZSCORE key member返回有序集合key中元素member的分值
ZINCRBY key increment member为有序集合key中元素member的分值加上increment
ZCARD key返回有序集合key中元素个数
ZRANGE key start stop [WITHSCORES]正序获取有序集合key从start下标到stop下标的元素
ZREVRANGE key start stop [WITHSCORES]倒序获取有序集合key从start下标到stop下标的元素

zset的基本使用

> ZADD books 9.0 "think in java"
> ZADD books 8.9 "java concurrency"
> ZADD books 8.6 "java cookbook"

> ZRANGE books 0 -1     # 按 score 排序列出,参数区间为排名范围
1) "java cookbook"
2) "java concurrency"
3) "think in java"

> ZREVRANGE books 0 -1  # 按 score 逆序列出,参数区间为排名范围
1) "think in java"
2) "java concurrency"
3) "java cookbook"

> ZCARD books           # 相当于 count()
(integer) 3

> ZSCORE books "java concurrency"   # 获取指定 value 的 score
"8.9000000000000004"                # 内部 score 使用 double 类型进行存储,所以存在小数点精度问题

> ZRANK books "java concurrency"    # 排名
(integer) 1

> ZRANGEBYSCORE books 0 8.91        # 根据分值区间遍历 zset
1) "java cookbook"
2) "java concurrency"

> ZRANGEBYSCORE books -inf 8.91 withscores  # 根据分值区间 (-∞, 8.91] 遍历 zset,同时返回分值。inf 代表 infinite,无穷大的意思。
1) "java cookbook"
2) "8.5999999999999996"
3) "java concurrency"
4) "8.9000000000000004"

> ZREM books "java concurrency"             # 删除 value
(integer) 1
> ZRANGE books 0 -1
1) "java cookbook"
2) "think in java

zset应用场景

  • 实现热搜排行榜
    ①:点击 “国庆放假” 新闻时,为其分值+1
    ZINCRBY hotNews:20190819 1 国庆放假
    ②:展示当日排行前十
    ZREVRANGE hotNews:20190819 0 9 WITHSCORES
    ③:七日搜索榜单计算
    取7天的key求并集放入新的key=hotNews:20190813-20190819中,就得出这7天中的访问量排行榜
    ZUNIONSTORE hotNews:20190813-20190819 7
    hotNews:20190813 hotNews:20190814… hotNews:20190819
    ④:展示七日排行前十
    根据上边的并集,从新的key=hotNews:20190813-20190819中取出前10名
    ZREVRANGE hotNews:20190813-20190819 0 9 WITHSCORES

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

「RISC-V Arch」RISC-V 规范结构

日期:20230228 规范分类 根据 RISC-V 设计哲学,其规范文档也是高度模块化的: ISA 规范(2 篇) 非特权规范特权规范 非 ISA 规范(6篇) Trace规范ABI 规范外部调试规范PLIC 规范SBI 规范UEFI 协…

华为OD机试题,用 Java 解【计算网络信号】问题

最近更新的博客 华为OD机试题,用 Java 解【停车场车辆统计】问题华为OD机试题,用 Java 解【字符串变换最小字符串】问题华为OD机试题,用 Java 解【计算最大乘积】问题华为OD机试题,用 Java 解【DNA 序列】问题华为OD机试 - 组成最大数(Java) | 机试题算法思路 【2023】使…

微软徐明强:谈谈ChatGPT及对技术的重新思考

是2023 Microsoft Azure中国区年度技术峰会启幕之际,Azure 云科技推出的专栏。我们邀请了业界富有前瞻视野的技术、业务专家,畅谈行业洞察,共享创新心得。本期专栏文章中,微软全渠道事业部首席技术官徐明强首次在 ChatGPT 爆火后分…

Java知识复习(四)多线程、并发编程

1、进程、线程和程序 进程:进程是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的;在 Java 中,当我们启动 main 函数时其实就是启动了一个 JVM 的进程,而 main 函数所在的线程就是这个进程…

JAVA开发(JAVA垃圾回收的几种常见算法)

JAVA GC 是JAVA虚拟机中的一个系统或者说是一个服务,专门是用于内存回收,交还给虚拟机的功能。 JAVA语言相对其他语言除了跨平台性,还有一个最重要的功能是JAVA语言封装了对内存的自动回收。俗称垃圾回收器。所以有时候我们不得不承认&#…

超实用的公众号用户运营方案分享,纯干货

公众运营是以用户为主的: 但是你知道什么是用户运营吗?你的公众号有没有维护好目标用户群体呢?你知道该怎么分析你的公众号用户群体吗?你知道分析完之后具体应该怎么做用户运营吗? 接下来伯乐网络传媒就来给大家分享…

第八届蓝桥杯省赛——7EXCLE地址

题目:Excel单元格的地址表示很有趣,它使用字母来表示列号。比如,A表示第1列,B表示第2列,Z表示第26列,AA表示第27列,AB表示第28列,BA表示第53列,....当然Excel的最大列号是…

【Spring Cloud Alibaba】(五)Dubbo启动报错?一直重连报错?你值得学习的是排查问题的方法

系列目录 【Spring Cloud Alibaba】(一)微服务介绍 及 Nacos注册中心实战 【Spring Cloud Alibaba】(二)微服务调用组件Feign原理实战 【Spring Cloud Alibaba】(三)OpenFeign扩展点实战 源码详解 【Spri…

2.1操作系统-进程管理:进程基本概念、进程与程序、进程与线程、进程的状态、进程三态模型、进程五态模型

2.1操作系统-进程管理:进程基本概念、进程与程序、进程与线程、进程的状态、进程三态模型、进程五态模型进程基本概念进程与程序进程与线程进程的状态进程三态模型进程五态模型进程基本概念 进程是程序在一个数据集合上运行的过程(运行的过程&#xff0…

智能驾驶词典 --- 自动驾驶芯片梳理

0 前言 与智能驾驶相关的芯片主要分为自动驾驶芯片(边缘端)和智能座舱芯片两大类,另外衍生的相关芯片种类还有计算集群芯片(云端), 1 自动驾驶芯片梳理 目前业内具有代表性的智驾芯片产品梳理如下。 1…

Studio 3T使用教程,本人详细介绍连接Mongodb过程

1:安装好MongodbWindows下安装 MongoDB_mongodb windows_Dragon-v的博客-CSDN博客2:安装好Studio 3T3:打开 Studio 3T ,点击开始创建连接 4:点击 Manually configure my connection settings,然后next5&…

【MySQL之MySQL底层分析篇】系统学习MySQL,从应用SQL语法到底层知识讲解,这将是你见过最完成的知识体系

文章目录MySQL体系结构MySQL存储结构(以InnoDB为例)MySQL执行流程(以InnoDB为例)1. 数据写入原理2. 数据查询原理MySQL存储引擎1. 为什么需要不同的存储引擎2. 如何为数据指定不同的存储引擎,数据粒度又是多少3. MySQL…

28岁还是一事无成,现在想学习软件测试还来得及吗?

为什么会学习软件测试? 28岁了,算一下8年了,工作了一年,就没去工作就一-直在家,家里固定每个月给2000,偶尔一个月有四千,但依旧没钱,家里给了一套房子,出门200米就是地铁站&#xff…

【流程控制】JavaScript 全栈体系(五)

JavaScript 基础 第七章 运算符 一、赋值运算符 目标: 能够使用赋值运算符简化代码 赋值运算符:对变量进行赋值的运算符 已经学过的赋值运算符: 将等号右边的值赋予给左边, 要求左边必须是一个容器其他赋值运算符: -*/% 使用…

轻松实现内网穿透:实现远程访问你的私人网络

导语:内网穿透是什么?为什么我们需要它?今天我们将介绍这个令人惊叹的技术,让你实现远程访问你的私人网络。 使用内网穿透,轻松实现外网访问本地部署的网站 第一部分:什么是内网穿透? 通俗解释…

【LeetCode】剑指 Offer 18. 删除链表中重复的节点(题目二) p122 -- Java Version

题目链接:https://leetcode.cn/problems/remove-duplicates-from-sorted-list/ 1. 题目介绍(83. 删除排序链表中的重复元素) 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序…

机器学习-BM-FKNCN、BM-FKNN等分类器对比实验

目录 一、简介和环境准备 二、算法简介 2.1四种方法类: 2.1.1FKNN 2.1.2FKNCN 2.1.3BM-FKNN 2.1.3BM-FKNCN 2.2数据预处理 2.3输出视图 2.4调用各种方法看准确率 2.4.1BM-FKNCN 2.4.2BM-FKNN 2.4.3FKNCN 2.4.4FKNN 2.4.5KNN 一、简介和环境准备 k…

Java9之HttpClientAPI实战详解

Java9 之 HttpClientAPI 实战详解 前言 相信关注 java9 的小伙伴们都知道 java9 版本内置模块提供了 Http 功能,当然并不是说之前 jdk 之前并不支持,那么这次更新又多了什么呢?或者是解决了什么问题? 说明 自 JDK 1.0 以来&…

图灵完备及TypeScript图灵完备性验证

一、图灵完备 1.图灵完备的概念 首先从定义出发,什么是图灵完备:图灵完备指一系列操作数据的规则能够模拟任何图灵机。 WikiPedia-图灵完备介绍,在可计算性理论,如果一系列操作数据的规则(如指令集、编程语言、细胞自…

centos安装Anaconda3

目录一、参考二、Anaconda简介1、用途2、关于anaconda三、下载安装1、下载2、安装anaconda3、配置环境遍历4、测试配置结果5、设置显示前缀一、参考 在centos上安装Anaconda 最新Anaconda3的安装配置及使用教程(附图文) 二、Anaconda简介 一句话&…