前言

Redis不是一个简单的键值对存储,它实际上是一个支持各种类型数据结构的存储。在传统的键值存储中,是将字符串键关联到字符串值,但是在Redis中,这些值不仅限于简单的字符串,还可以支持更复杂的数据结构。下面就是Redis支持的数据结构:

  • 字符串(String):二进制安全字符串。
  • 列表(List):根据插入顺序排序的字符串元素列表,基于链表实现。
  • 集合(Set):唯一的乱序的字符串元素的集合。
  • 有序集合(Sorted Set):与集合类似,但是每个字符串元素都与一个称为score的数字相关联。 元素总是按其score排序,并且可以检索一定score范围的元素。
  • 哈希(Hash):由字段与值相关联组成的映射,字段和值都是字符串。
  • 位图(Bitmap):像操作位数组一样操作字符串值,可以设置和清除某个位,对所有为1的位进行计数,找到第一个设置1的位,找到第一个设置0的位等等。
  • HyperLogLogs:一种概率数据结构,使用较小的内存空间来统计唯一元素的数量,误差小于1%。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

键(Key)

是二进制安全的,这意味着您可以使用任何二进制序列作为键,可以是OneMoreStudy这样的字符串,也可以使图片文件的内容,空字符串也是有效的。不过,还有一些其他规则:

  • 不要使用过长的,比如一个1KB的键。不仅是多占内存方面的问题,而是在数据集中查找可能需要进行一些耗时的比较。如果真的有比较大的,先对它进行哈希(比如:MD5SHA1)是一个好主意。
  • 也不要使用过短的,比如:OMS100f,相对于one-more-study:100:fans,后者更具有可读性。可能会占用更多内存,但是相对于值所占的内存,所增加的内存还是小很多的。我们要找到一个平衡点,不长也不短。
  • 多个字段以冒号分隔,一个字段内多个单词以连词符或点分隔,比如:one-more-study:100:fans,或者one.more.study:100:fans
  • 允许的最大值为512MB。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

字符串(String)

字符串类型是和关联的最简单的类型。它是Memcached中唯一的数据类型,因此对于新手来说,在Redis中使用它也是很容易的。是字符串类型,当我们也使用字符串类型作为值时,我们会可以从一个字符串映射到另一个字符串。 字符串数据类型有很多应用场景,例如缓存HTML片段或页面。

下面简单介绍一下字符串的命令(在redis-cli中使用):

> set one-more-key OneMoreStudy
OK
> get one-more-key
"OneMoreStudy"

使用SETGET命令来设置和查询字符串值的方式。需要注意的是,如果当前已经和字符串值相关联,SET命令将会替换已存储在中的现有值。字符串可以是任意的二进制数据,比如jpeg图像。字符串最多不能大于512MB。SET命令还有一些实用的可选参数,比如:

> set one-more-key Java nx   #如果key存在,则设置失败。
(nil)
> set one-more-key Java xx #如果key存在,才设置成功。
OK

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

虽然字符串是Redis的基本值,但也可以使用它们执行一些实用的操作。 比如:

> set one-more-counter 50
OK
> incr one-more-counter #自增加1
(integer) 51
> incr one-more-counter #自增加1
(integer) 52
> incrby one-more-counter 5 #自增加5
(integer) 57

INCR命令将字符串值解析为整数,将其自增加1,最后将获得的值设置为新值。 还有其他类似的命令,例如INCRBYDECRDECRBY等命令。 INCR命令是原子操作,即时有多个客户端同时同一个key的INCR命令,也不会进入竞态条件。比如,上面的例子先设置one-more-counter的值为50,即使两个客户端同时发出INCR命令,那么最后的值也肯定是52。

可以使用MSETMGET命令在单个命令中设置或查询多个的值,对于减少延迟也很有用。比如:

> mset a 1 b 2 c 3
OK
> mget a b c
1) "1"
2) "2"
3) "3"

使用MGET命令时,Redis返回一个值的数组。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

使用DEL命令可以删除和相关联的值,存在指定的则返回1,不存在指定的则返回0。使用EXISTS命令判断Redis中是否存在指定的,存在指定的则返回1,不存在指定的则返回0。比如:

> set one-more-key OneMoreStudy
OK
> exists one-more-key
(integer) 1
> del one-more-key
(integer) 1
> exists one-more-key
(integer) 0

使用TYPE命令,可以返回存储在指定key的值的数据类型,比如:

> set one-more-key OneMoreStudy
OK
> type one-more-key
string
> del one-more-key
(integer) 1
> type one-more-key
none

在讨论更复杂的数据结构之前,我们需要讨论另一个功能,该功能无论值类型是什么都适用,它就是EXPIRE命令。 它可以为设置到期时间,当超过这个到期时间后,该将自动销毁,就像对这个调用了DEL命令一样。比如:

> set one-more-key OneMoreStudy
OK
> expire one-more-key 5
(integer) 1
> get one-more-key #立刻调用
"OneMoreStudy"
> get one-more-key #5秒钟后调用
(nil)

上面的例子,适用了EXPIRE命令设置了过期时间,也可以使用PERSIST命令移除的过期时间,这个将持久保持。除了EXPIRE命令,还可以使用SET命令设置过期时间,比如:

> set one-more-key OneMoreStudy ex 10 #设置过期时间为10秒
OK
> ttl one-more-key
(integer) 9

上面的例子,设置了一个字符串值OneMoreStudyone-more-key,该的到期时间为10秒。之后,调用TTL命令以检查该的剩余生存时间。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

到期时间可以使用秒或毫秒精度进行设置,但到期时间的分辨率始终为1毫秒。实际上,Redis服务器上存储的不是到期时间长度,而是该到期的时间。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

列表(List)

Redis列表是使用链表实现的,这就意味着在头部或尾部增加或删除一个的元素的时间复杂度是O(1),非常快的。不过,按索引查询对应元素的时间复杂度就是O(n),慢很多。如果想快速查询大量数据,可以使用有序集合,后面会有介绍。

LPUSH命令将一个新元素添加到列表的左侧(顶部),而RPUSH命令将一个新元素添加到列表的右侧(底部)。最后,LRANGE命令可以从列表中按范围提取元素。比如:

> rpush one-more-list A
(integer) 1
> rpush one-more-list B
(integer) 2
> lpush one-more-list first
(integer) 3
> lrange one-more-list 0 -1
1) "first"
2) "A"
3) "B"

LRANGE命令需要另外两个参数,要返回的第一个元素的索引和最后一个元素的索引。如果索引为负值,Redis将从末尾开始计数,-1是列表的最后一个元素,-2是列表的倒数第二个元素,依此类推。

LPUSHRPUSH命令支持多个参数,可以使用一次命令添加多个元素,比如:

> rpush one-more-list 1 2 3 4 5 "last"
(integer) 9
> lrange one-more-list 0 -1
1) "first"
2) "A"
3) "B"
4) "1"
5) "2"
6) "3"
7) "4"
8) "5"
9) "last"

在Redis列表上,也可以移除并返回元素。 与LPUSHRPUSH命令,对应的就是LPOPRPOP命令,LPOP命令是将列表的左侧(顶部)的元素移除并返回,RPOP命令是将列表的右侧(底部)的元素移除并返回。比如:

> rpush one-more-list a b c
(integer) 3
> rpop one-more-list
"c"
> rpop one-more-list
"b"
> rpop one-more-list
"a"

我们添加了三个元素,并移除并返回了三个元素,此时列表为空,没有任何元素。如果再使用RPOP命令,会返回一个NULL值:

> rpop one-more-list
(nil)

使用RPUSHRPOP命令,或者LPUSHLPOP命令可以实现栈的功能,使用LPUSHRPOP命令,或者RPUSHLPOP命令可以实现队列的功能。也可以实现生产者和消费者模式,比如多个生产者使用LPUSH命令将任务添加到列表中,多个消费者使用RPOP命令将任务从列表中取出。但是,有时列表可能为空,没有任何要处理的任务,因此RPOP命令仅返回NULL。在这种情况下,消费者被迫等待一段时间,然后使用RPOP命令重试。这就暴露了有几个缺点:

  1. 客户端和服务端之间可以处理无用的命令,因为在列表为空时的所有请求将无法完成任何实际工作,它们只会返回NULL
  2. 由于消费者在收到NULL之后会等待一段时间,因此会增加任务处理的延迟。为了减小延迟,我们可以在两次调用RPOP之间等待更少的时间,这就扩大了更多对Redis的无用调用。

有什么办法可以解决呢?使用BRPOPBLPOP的命令,它们和RPOPLPOP命令类似,唯一的区别是:如果列表为空时,命令会被阻塞,直到有新元素添加到列表中,或指定的超时时间到了时,它们才会返回到调用方。比如:

> brpop tasks 5

它含义是,列表为空时,等待列表中的元素,但如果5秒钟后没有新的元素被添加,则返回。您可以将超时时间传入0,表示永远等待元素添加。也可以传入多个列表,这时会按参数先后顺序依次检查各个列表,返回第一个非空列表的尾部元素。另外还有以下3点需要注意的:

  1. 当列表为空,并且有多个客户端在等待时,有一个新的元素被添加到列表中,它会被第一个等待的客户端获取到,以此类推。
  2. 返回值与RPOP命令相比有所不同,它是一个包含两个元素的数组,包含key和对应的元素,因为BRPOPBLPOP命令能够阻止等待来自多个列表的元素。
  3. 超过了超时时间,会返回NULL

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

列表的创建和删除都是由Redis自动完成的,当尝试向不存在的添加元素时,Redis会自动创建一个空的列表;当最后一个元素被移除时,Redis会自动删除这个列表。这不是特定于列表的,它适用于由多个元素组成的所有Redis数据类型,比如集合、有序集合、哈希,它们都有3条规则:

  1. 当我们将元素添加到聚合数据类型时,如果目标不存在,则在添加元素之前会创建一个空的聚合数据类型。比如:
> del one-more-list
(integer) 1
> lpush one-more-list 1 2 3
(integer) 3

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

但是,在存在时,就不能操作错误的数据类型了,比如:

> set one-more-key OneMoreStudy
OK
> lpush one-more-key 1 2 3
(error) WRONGTYPE Operation against a key holding the wrong kind of value
> type one-more-key
string
  1. 当我们从聚合数据类型中删除元素时,如果该值保持为空,则key将自动销毁。比如:
> lpush one-more-list 1 2 3
(integer) 3
> exists one-more-list
(integer) 1
> lpop one-more-list
"3"
> lpop one-more-list
"2"
> lpop one-more-list
"1"
> exists one-more-list
(integer) 0
  1. 当对应key不存在,并且调用只读命令(如LLEN命令,获取列表长度)或写命令(如LPOP命令)时,都会返回空聚合数据类型的结果。比如:
> del one-more-list
(integer) 0
> llen one-more-list
(integer) 0
> lpop one-more-list
(nil)

Redis为了追求高性能,列表的内部实现不是一个简单的链表,这里先卖个关子,后续的文章会详细介绍。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

集合(Set)

集合是一个字符串的无序集合,SADD命令可以将新元素添加到集合中。还可以对集合进行许多其他操作,例如:判断给定元素是否已存在、执行多个集合之间的交集、并集或差等等。比如:

> sadd one-more-set 1 2 3
(integer) 3
> smembers one-more-set
1) "1"
2) "3"
3) "2"

在上面的例子中,在集合中添加了三个元素,并让Redis返回所有元素。 正如你所见,返回的元素是没有排序的。在每次调用时,元素的顺序都有可能不一样。

还可以使用SISMEMBER命令判断给定元素是否已存在,比如:

> sismember one-more-set 3
(integer) 1
> sismember one-more-set 30
(integer) 0

在上面的例子中,3在集合中,所以返回1;而30不在集合中,所以返回0。

可以使用SINTER命令,计算出多个集合的交集;使用SUNION命令,计算多个集合的并集;使用SPOP命令,移除并返回集合中的一个随机元素;使用SCARD命令,计算集合中的元素的数量。比如:

> sadd one-more-set1 1 2 3
(integer) 3
> sadd one-more-set2 2 3 4
(integer) 3
> sinter one-more-set1 one-more-set2 #交集
1) "3"
2) "2"
> sunion one-more-set1 one-more-set2 #并集
1) "1"
2) "3"
3) "2"
4) "4"
> spop one-more-set1 #随机移除一个元素
"3"
> scard one-more-set1 #元素数量
(integer) 2

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

有序集合(Sorted Set)

有序集合是一种类似于集合和哈希之间混合的数据类型。像集合一样,有序集合中由唯一的、非重复的字符串元素组成,因此从某种意义上说,有序集合也是一个集合。但是集合中的元素是没有排序的,而有序集合中的每个元素都与一个称为分数(score)的浮点值相关联,这就是为什么有序集合也类似于哈希的原因,因为每个元素都映射到一个值。有序集合的排序规则如下:

  • 如果A和B是两个具有不同分数的元素,那么如果A.分数>B.分数,则A>B。
  • 如果A和B的分数完全相同,那么如果A字符串在字典排序上大于B字符串,则A>B。 A和B字符串不能相等,因为有序集合中的元素都是唯一的。

我们来举个例子,把王者荣耀战队的名字和积分添加到有序集合中,其中把战队的名字作为值,把战队的积分作为分数。

> zadd kpl 12 "eStarPro"
(integer) 1
> zadd kpl 12 "QGhappy"
(integer) 1
> zadd kpl 10 "XQ"
(integer) 1
> zadd kpl 8 "EDG.M"
(integer) 1
> zadd kpl 8 "RNG.M"
(integer) 1
> zadd kpl 4 "TES"
(integer) 1
> zadd kpl 2 "VG"
(integer) 1

如上所示,ZADD命令和SADD命令相似,但是多了一个额外的参数(在要添加的元素的前面)作为分数。ZADD命令也支持多个参数,虽然在上面的例子中未使用它,但你也可以指定多个分数和值对。使用有序集合,快速地返回按其积分排序的战队列表,因为实际上它们已经被排序了。

需要注意的是,为了快速获取有序集合中的元素,每次添加元素的时间复杂度都为O(log(N)),这是因为有序集合是同时使用跳跃表和字典来实现的,具体原理这里先卖个关子,后续的文章会详细介绍。

可以使用ZRANGE命令按照升序获取对应的值,比如:

> zrange kpl 0 -1
1) "VG"
2) "TES"
3) "EDG.M"
4) "RNG.M"
5) "XQ"
6) "QGhappy"
7) "eStarPro"

0和-1代表查询从第一个到最后一个的元素。还可以使用ZREVRANGE命令按照降序获取对应的值,比如:

> zrevrange kpl 0 -1
1) "eStarPro"
2) "QGhappy"
3) "XQ"
4) "RNG.M"
5) "EDG.M"
6) "TES"
7) "VG"

加上WITHSCORES参数,就可以连同分数一起返回,比如:

> zrange kpl 0 -1 withscores
1) "VG"
2) "2"
3) "TES"
4) "4"
5) "EDG.M"
6) "8"
7) "RNG.M"
8) "8"
9) "XQ"
10) "10"
11) "QGhappy"
12) "12"
13) "eStarPro"
14) "12"

有序集合还有更强大的功能,比如在分数范围内操作,让我们获取小于10(含)的战队,使用ZRANGEBYSCORE命令:

> zrangebyscore kpl -inf 10
1) "VG"
2) "TES"
3) "EDG.M"
4) "RNG.M"
5) "XQ"

这就是获取分数从负无穷到10所对应的值,同样的我们也可以获取分数从4到10所对应的值:

> zrangebyscore kpl 4 10
1) "TES"
2) "EDG.M"
3) "RNG.M"
4) "XQ"

另外有用的命令:ZRANK命令,它可以返回指定值的升序排名(从0开始);ZREVRANK命令,它可以返回指定值的降序排名(从0开始),比如:

> zrank kpl "EDG.M"
(integer) 2
> zrevrank kpl "EDG.M"
(integer) 4

有序集合的分数是随时更新的,只要对已有的有序集合调用ZADD命令,就会以O(log(N))时间复杂度更新其分数和排序。这样,当有大量更新时,有序集合是合适的。由于这种特性,常见的场景是排行榜,可以方便地显示排名前N位的用户和用户在排行榜中的排名。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

哈希(Hash)

Redis的哈希和人们期望的“哈希”结构是一样的,它是一个无序哈希,内部存储了很多键值对,比如:

> hmset one-more-fans:100 name Lily age 25
OK
> hget one-more-fans:100 name
"Lily"
> hget one-more-fans:100 age
"25"
> hgetall one-more-fans:100
1) "name"
2) "Lily"
3) "age"
4) "25"

尽管哈希很容易用来表示对象,但是实际上可以放入哈希中的字段数是没有实际限制的,因此您可以以更多种的不同方式使用哈希。除了HGET命令获取单个字段对应的值,也可以使用HMSET命令获取多个字段及对应的值,它返回的是一个数组,比如:

> hmget one-more-fans:100 name age non-existent-field
1) "Lily"
2) "25"
3) (nil)

还可以使用HINCRBY命令,为指定字段的值做增量,比如:

> hget one-more-fans:100 age
"25"
> hincrby one-more-fans:100 age 3
(integer) 28
> hget one-more-fans:100 age
"28"

Redis哈希的实现结构,和Java中的HashMap是一样的,也是“数组+链表”的结构,当发生数组位置碰撞是,就会将碰撞的元素用链表串起来。不过Redis为了追求高性能,rehash的方式不太一样,这里先卖个关子,后续的文章会详细介绍。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

位图(Bitmap)

位图不是实际的数据类型,而是在String类型上定义的一组面向位的操作。 由于字符串是二进制安全的,并且最大长度为512MB,因此可以设置多达2^32个不同的位。位图操作分为两类:固定单个位操作,比如将一个位设置为1或0或获取其值;对位组的操作,比如计算给定位范围内设置位的数量。

位图的最大优点之一是,它们在存储信息时通常可以节省大量空间。例如,在以增量用户ID位标识表示用户是否要接收新闻通讯,仅使用512 MB内存就可以记住40亿用户的一位信息。

使用SETBITGETBIT命令来设置和获取指定位,比如:

> setbit one-more-key 10 1
(integer) 0
> getbit one-more-key 10
(integer) 1
> getbit one-more-key 11
(integer) 0

SETBIT命令将位号作为其第一个参数,将其设置为1或0的值作为其第二个参数。如果位号超出当前字符串长度,该命令将会自动扩大字符串。GETBIT命令只是返回指定位号的位的值,如果位号超出存储的字符串长度则会返回0。

对位组的操作有以下3个命令:

  1. BITOP命令可以在不同的字符串之间执行按位运算,提供的位运算有与、或、非和异或。
  2. BITCOUNT命令可以统计指定范围内位数为1的个数。
  3. BITPOS命令可以查找指定范围内为0或1的第一位。
> set one-more-key "\x13\x7f" #二进制为0001 0011 0111 1111
OK
> bitcount one-more-key #整个字符串中1的位数
(integer) 10
> bitcount one-more-key 0 0 #第一个字符(0001 0011)中1的位数
(integer) 3
> bitcount one-more-key 1 1 #第二个字符(0111 1111)中1的位数
(integer) 7
> bitpos one-more-key 0 #整个字符串中第一个0位
(integer) 0
> bitpos one-more-key 1 #整个字符串中第一个1位
(integer) 3
> bitpos one-more-key 1 0 0 #第一个字符(0001 0011)中第一个1位
(integer) 3
> bitpos one-more-key 1 1 1 #第二个字符(0111 1111)中第一个1位
(integer) 9

位图可以应用于各类实时分析,也可以节省空间高效地存储位信息。比如,记录用户每天的签到数据,每一个位表示用户是否签到过,这样就可以计算出某个时间段用户签到了几次,某个时间段用户第一次签到是哪一天。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

HyperLogLogs

HyperLogLog是一种概率数据结构,用于统计唯一元素的数量,也可以理解为估计集合中元素的个数。

通常情况下,对唯一元素进行统计数量时,需要使用与要统计的元素数量成比例的内存量,因为需要记住过去已经看到的元素,以避免多次对其进行统计。但是,有一组算法可以以内存换取精度,最终会得到带有标准误差的估计数量,在Redis的HyperLogLogs中,该误差小于1%。

这个算法的神奇之处在于,不再需要使用与所统计元素数量成比例的内存量,而可以使用恒定数量的内存。在最坏的情况下占据12KB的内存空间,Redis对HyperLogLog的存储进行了优化,在计数比较少时,占据的内存空间会更小,这里先卖个关子,后续的文章会详细介绍其中原理。

在集合中,可以将每个元素添加到集合中,并使用SCARD命令获取集合中的元素数量,因为SADD命令不会重新添加现有元素,所以元素都是唯一的。HyperLogLog的操作和集合比较类似,使用PFADD命令将元素添加到HyperLogLog中,类似于集合的SADD命令;使用PFCOUNT命令获取HyperLogLog中的唯一元素的当前近似值数量,类似于集合的SCARD命令。比如:

> pfadd one-more-hll a b c d e
(integer) 1
> pfcount one-more-hll
(integer) 5

Redis中的HyperLogLog尽管在技术上是不同的数据结构,但被编码为字符串,因此可以调用GET命令来序列化HyperLogLog,然后调用SET命令来将其反序列化回服务器。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

总结

Redis提供更加丰富的数据结构,(Key)和字符串(String),都是二进制安全的字符串;列表(List),根据插入顺序排序的字符串元素列表,基于链表实现;集合(Set),唯一的乱序的字符串元素的集合;有序集合(Sorted Set),与集合类似,但是每个字符串元素都与一个称为score的数字相关联;哈希(Hash),由字段与值相关联组成的映射,字段和值都是字符串;位图(Bitmap),像操作位数组一样操作字符串值,可以设置和清除某个位,对所有为1的位进行计数,找到第一个设置1的位,找到第一个设置0的位等等;HyperLogLogs,一种概率数据结构,使用较小的内存空间来统计唯一元素的数量,误差小于1%。

欢迎关注微信公众号:万猫学社,每周一分享Java技术干货。

面试中经常问到的Redis七种数据类型,你都真正了解吗?的更多相关文章

  1. 面试中常问的List去重问题,你都答对了吗?

    面试中经常被问到的list如何去重,用来考察你对list数据结构,以及相关方法的掌握,体现你的java基础学的是否牢固. 我们大家都知道,set集合的特点就是没有重复的元素.如果集合中的数据类型是基本 ...

  2. 2 万字 + 20张图| 细说 Redis 九种数据类型和应用场景

    作者:小林coding 计算机八股文网(操作系统.计算机网络.计算机组成.MySQL.Redis):https://xiaolincoding.com 大家好,我是小林. 我们都知道 Redis 提供 ...

  3. 细说 JavaScript 七种数据类型

    在 JavaScript 规范中,共定义了七种数据类型,分为 “基本类型” 和 “引用类型” 两大类,如下所示: 基本类型:String.Number.Boolean.Symbol.Undefined ...

  4. redis五种数据类型的使用场景

    string 1.String 常用命令: 除了get.set.incr.decr mget等操作外,Redis还提供了下面一些操作: 获取字符串长度 往字符串append内容 设置和获取字符串的某一 ...

  5. Symbol -- JavaScript 语言的第七种数据类型

    ES5 的对象属性名都是字符串,这容易造成属性名的冲突.比如,你使用了一个他人提供的对象,但又想为这个对象添加新的方法(mixin 模式),新方法的名字就有可能与现有方法产生冲突.如果有一种机制,保证 ...

  6. Redis五种数据类型-设置key的过期时间

    1.redis命令客户端 [root@localhost bin]# ./redis-cli 127.0.0.1:6379> #是否运行着 127.0.0.1:6379> ping PON ...

  7. JavaScript 七种数据类型

    在 JavaScript 规范中,共定义了七种数据类型,分为 “基本类型” 和 “引用类型” 两大类,如下所示: 基本类型:String.Number.Boolean.Symbol.Undefined ...

  8. ES6 之 第七种数据类型Symbol

    概述 为了减少对象的属性名冲突,ES6引入新的原始数据类型Symbol,JS的第七种数据类型. Symbol 能够保证每个属性的名字都是独一无二,这样就能从根本上防止属性名冲突. Symbol 值能够 ...

  9. 【面试题】JS第七种数据类型Symbol详解

    JS第七种数据类型Symbol详解 点击打开视频讲解更加详细 一.什么是Symbol? Symbol是ES6中引入的一种新的基本数据类型,用于表示一个独一无二的值.它是JavaScript中的第 七种 ...

随机推荐

  1. Duplicate keys detected: '0'. This may cause an update error.

    在运行vue项目的时候报了:[Vue warn]: Duplicate keys detected: ‘0’. This may cause an update error(错误,检测到重复的key值 ...

  2. POJ2185 Milking Grid 题解 KMP算法

    题目链接:http://poj.org/problem?id=2185 题目大意:求一个二维的字符串矩阵的最小覆盖子矩阵,即这个最小覆盖子矩阵在二维空间上不断翻倍后能覆盖原始矩阵. 题目分析:next ...

  3. jq实现二级菜单/下拉菜单

    https://www.cnblogs.com/sandraryan/ 不是很难,直接上代码~ 有写注释 <!DOCTYPE html> <html lang="en&qu ...

  4. js基础——面向对象(构造函数)

    1.面向对象:类的标志,通过类可创建多个具有相同属性和方法的对象 2.创建对象 1)工厂模式方式:避免重复实例化但未能解决识别问题  function boss(name, age) {       ...

  5. tensorflow在文本处理中的使用——Word2Vec预测

    代码来源于:tensorflow机器学习实战指南(曾益强 译,2017年9月)——第七章:自然语言处理 代码地址:https://github.com/nfmcclure/tensorflow-coo ...

  6. Less 语法快速入门

    Less 语法快速入门 Less 是一门 CSS 预处理语言其可以运行在 Node 或浏览器端. 它将传统的 css 样式结构单一的排版顺序进行了优化,让我们可以通过层级嵌套的方式将 css 类名与H ...

  7. TOJ5705动态序列操作(STL or treap)

    传送门:动态序列操作 在一个动态变化的序列中,完成以下基本操作: (1)插入一个整数 (2)删除一个整数 (3)查找序列中最大的数 (4)查找序列中最小的数 (5)求x的前驱(前驱定义为不大于x的序列 ...

  8. C#面试题整理(带答案)

    1.维护数据库的完整性.一致性.你喜欢用触发器还是自写业务逻辑?为什么? 答:尽可能用约束(包括CHECK.主键.唯一键.外键.非空字段)实现,这种方式的效率最好:其次用触发器,这种方式可以保证无论何 ...

  9. C++ 图片格式转化和压缩

    在做人脸识别底库图片导入的时候,需要支持主流的图片的格式,如jpeg.bmp.png等格式.所以需要对图片进行格式转化.图片过大的话,还有进行缩放等.本文介绍的是利用cximage开源库,来进行对图片 ...

  10. 2018-8-10-win10-uwp-Window.Current.Dispatcher中Current为null

    title author date CreateTime categories win10 uwp Window.Current.Dispatcher中Current为null lindexi 201 ...