Spring Boot进阶,开发社区核心功能

这里可能被问到考点是:

考点1:敏感词过滤算法

考点分析


敏感词过滤算法,文中用的是 前缀树,其实大家有空也可以了解一下其他的,比如正则匹配,KMP等,了解他们的优缺点。

我这里做一个方便你们理解的问答:

(1)除了前缀树,还可以用哪些方法来进行过滤?可以简单比较一下优缺点吗?(本质还是字符串匹配问题,可以了解下其他方法,其实市面上并不是用前缀树,所以我们这里只是自己学习 + 轻量级)

(2)为什么要过滤敏感词呢?你是怎么维护敏感词库的?(就是要想清楚为啥要过滤,比如为了网站安全啊,因为涉及政治不正确的,可能你网站就凉了;为了避免低俗辱骂啊,比如王者荣耀这些也会过滤。怎么维护的话,就是你词库肯定不能写死在代码里是吧,得可能动态添加/删除敏感词)

(3)前缀树还有其他应用场景吗?(自己百度搜索吧)

问答总结(附答案)

前缀树是怎么实现的?说一下插入和查找的复杂度?

基础知识:

前缀树,也就是字典树,用来高效地存储和查找字符串。每个节点在树中代表一个字符,从根节点到任何一个节点的路径都代表一个字符串的前缀。每个节点主要有两个部分:一个是指向子节点的集合,另一个是一个布尔值,用来标记这个节点是否是某个单词的结尾。

当你要往前缀树里插入一个新字符串时,你会从根节点开始,一次处理字符串中的每一个字符。如果当前字符对应的节点还不存在,你就创建一个新的节点。这样操作的时间复杂度是 O(n),其中 n 是你要插入的字符串的长度。空间复杂度方面,如果插入的字符串和树中已有的字符串有很多重叠部分,那么你只需要额外的空间来存储那些新的、不重复的节点,空间复杂度可能会是 O(1)。但如果你插入的字符串完全没有重叠,那最坏情况下空间复杂度可能会达到 O(n),因为你可能需要为每个新字符都创建新的节点。

至于查找一个字符串的过程也是类似的。你从根节点开始,依次查找字符串中的每个字符。如果每个字符的节点都存在,并且最后一个字符的节点标记为结束,那么这个字符串就是树中已有的。查找的时间复杂度同样是 O(n),因为你要检查每个字符。空间复杂度在查找时是 O(1),因为查找过程只涉及访问已有的节点,不需要额外的存储空间。

具体实现:

我们计划使用两种不同的方法。第一种方法是直接利用Java提供的字符串操作API,具体来说,就是使用contains()方法。这种方法的思路很直接:我们遍历每一个需要检测的字符串,然后依次检查这个字符串是否包含我们的敏感词列表中的任何一个词。如果包含,我们就认定它是敏感词。这种方式很方便,因为Java已经为我们提供了内置的字符串匹配功能,我们只需要调用相关方法即可。

为了进行测试,我们需要生成一些数据。我们会生成一个包含10万个随机字符串的文件,这些字符串会被用作测试数据。生成数据后,我们还需要准备一个敏感词列表,这个列表会被存储在名为sensitive_words.txt的文件中。文件的格式非常简单,每一行代表一个敏感词,比如“badword1”、“badword2”这样的词语。

第二种方法是使用前缀树,也叫Trie。前缀树是一种特殊的树结构,非常适合处理前缀匹配问题。在实现过程中,我们首先要构建这个前缀树。我们会写一个方法来读取sensitive_words.txt文件,把每一个敏感词逐一插入到前缀树中。插入的过程是这样:我们从根节点开始,根据敏感词的每一个字符,逐级创建或查找对应的子节点,直到整个词都被插入到前缀树里。为了表示某个节点是一个词的结束,我们还会在最后一个字符对应的节点上打一个标记。通过这种方式,前缀树能够快速地判断一个字符串是否以某个敏感词为前缀或者是否完全匹配某个敏感词。

接着,我们要对这两种方法的性能进行测试。我们会分别使用这两种方法来检测10万条测试数据中的敏感词,并且记录下它们所花的时间。对于Java原生API的方式,我们就是简单地遍历每一个测试字符串,然后用contains()方法去检查是否包含任何一个敏感词。而对于前缀树的方法,我们会遍历每一个测试字符串,然后用前缀树提供的搜索功能来检查这个字符串中是否包含敏感词。

测试完成后,我们会对比两种方法的执行时间,看看哪一种在处理大规模数据时表现得更好。Java原生API的contains()方法虽然直接,但可能在处理大量数据或复杂匹配时效率不如前缀树。而前缀树的优势在于,它特别适合频繁的前缀匹配或敏感词查找任务,因为它能够在较短时间内定位到匹配的词语。

前缀树什么时候开始构建和加载数据?

最初,我们可能会选择在项目启动时就构建前缀树,这样可以确保在系统运行的每个时刻,前缀树都能提供最新的数据。这样做的好处是,系统启动后就能立即提供敏感词过滤的功能,不会有延迟。

不过,这种方法也有缺点。比如,如果敏感词表发生变化,我们需要重新构建前缀树以确保新的敏感词被及时加载,这可能会对系统性能产生影响。此外,对于那些只浏览内容而不发帖或评论的用户来说,前缀树的构建可能会显得多余,因为他们不会触发敏感词的处理。

一种思路是设置定期任务来更新前缀树。例如,可以定时检查敏感词表的变化,然后更新前缀树。这种方式能有效地保持前缀树的最新状态,同时减少了项目启动时的负担。对于那些只浏览不互动的用户,可以选择在他们实际进行发帖或评论操作时才加载前缀树,或根据实际需要进行预加载。这样做能减少内存占用,提升系统的响应速度。

前缀树还有其他应用场景吗?

前缀树确实有很多有用的应用场景,除了我们常见的敏感词过滤,它还可以用于很多其他功能。比如,自动补全就是一个典型的应用场景。在输入框中,当用户输入一部分词汇时,前缀树可以帮助系统快速找到所有以该前缀开头的词汇,从而给出相关的自动补全建议。这种功能在搜索引擎和文本输入系统中非常常见。

另外,拼写检查也是前缀树的一项重要应用。在拼写检查的过程中,系统可以通过前缀树快速检查用户输入的单词是否在字典中存在,如果没有找到匹配的词汇,就可以给出拼写错误的提示,并可能提供修正建议。

前缀树还可以用于统计和分析,比如每年统计十大热词的工作。通过前缀树记录和更新热门词汇,系统可以有效地跟踪词汇的使用频率,并根据统计数据识别出最常使用的词汇。这对于语言处理、文本分析等任务非常有用。

考点2:评论系统设计

考点分析

之后就是评论系统的设计了,

1、比如评论太多了怎么办?一个视频百万评论,你展示的时候怎么展示?sql语句怎么写好?
2、又比如如果一个评论,有很多层对话,数据结构应该怎么设计呢?最多可以镶嵌多少层呢?

这些都是和你评论系统设计有关,如果你这块学习的好,可以把这块重点写进 简历里。

如果针对评论系统,你想要给简历做包装,更加深入学习评论系统,可以看这个视频:17. 评论系统设计 Comment system

评论系统问答(附带答案)

说一下你的评论系统是怎么设计的?

都是基于mysql的用户表和评论表来实现,用户提交评论,包含了文章的id,评论的内容以及可选的父评论id。数据库验证用户的身份,随后存储评论内容放入数据库,返回一个评论id和时间戳。 服务器根据文章ID查询所有评论,并按时间顺序排序。

评论表包括评论id,评论者id,被评论的评论id,内容,时间戳,点赞数等内容。

对于多级评论,你会如何设计?

多级评论可以通过parentid字段来解决。顶级评论的该字段为null,然后递归向下找就可以得到评论的层级结构。

这里可能涉及到评论树相关的内容, 是用于表示评论及其回复之间层级关系的一种数据结构。它类似于树状结构,每个评论可以有多个子评论,从而形成一个多级嵌套的层次关系 。 通过树状结构,评论及其回复的关系层次分明,易于理解和导航。 也能够方便前端同学的代码实现。

评论的展示顺序是如何确定的?有哪些排序规则?

在我们的系统中,评论的展示顺序可以通过多种方式来确定,主要取决于具体的需求和用户体验。常用的排序规则包括以下几种:

首先,可以根据评论在数据库中的时间戳来排序。这样我们可以按时间顺序展示评论。比如,可以选择升序排列,这样最早的评论会排在最前面;也可以选择降序排列,这样最新的评论会排在最前面。这种排序方式非常直观,用户可以很容易地看到最新的互动或者从头开始阅读所有评论。

其次,我们可以根据评论的点赞数来排序。这种方式下,点赞数越多的评论会排在越前面,通常用于展示那些被认为更有价值或更受欢迎的评论。为了实现这种排序,可以使用Redis的有序集合(zset)。在有序集合中,每个元素都会有一个分数,我们可以将评论的ID作为元素,点赞数作为分数,这样就可以轻松实现基于点赞数的排序。

此外,还有一种常见的排序方式是综合排序,即结合时间和点赞数等多个因素,使用一定的加权算法来确定评论的最终排序。这种方式可以同时考虑评论的时效性和受欢迎程度,提供更平衡的展示效果。比如,我们可以给每条评论的时间戳和点赞数赋予不同的权重,然后计算一个综合得分,按得分排序。

总的来说,评论的展示顺序可以灵活调整,具体选择哪种排序规则可以根据具体场景和用户需求来决定。通过合理的排序,可以提升用户的阅读体验,使重要或热门的评论更容易被发现和互动。

对于热门评论和最新评论,你是如何进行排序和展示的?

在系统中,对于热门评论和最新评论的排序和展示,我们会采用不同的策略来确保用户能够方便地看到最重要和最新的内容。

首先,热门评论通常是指那些得到最多点赞或回复的评论。为了实现热门评论的排序,我们会综合考虑评论的点赞数、回复数和其他可能的互动指标。常见的方法是使用Redis的有序集合(zset)来存储评论的ID和其对应的得分。得分可以是点赞数、回复数等指标的加权和。比如,我们可以给每条评论的点赞数和回复数赋予不同的权重,计算一个综合得分,然后根据得分对评论进行排序。这样,得分最高的评论会排在最前面,确保用户能看到最受欢迎的评论。

其次,最新评论是指按照发布时间排序的评论。这种排序方式非常直观,可以让用户看到最新的互动情况。具体实现上,我们会根据评论在数据库中的时间戳进行排序。可以选择降序排列,这样最新的评论会排在最前面。这个过程可以在数据库查询时通过SQL语句直接实现,例如使用ORDER BY子句按时间戳降序排列。

为了确保用户能同时看到热门评论和最新评论,我们通常会在页面上分开展示这两类评论。比如,页面的顶部或显眼位置展示几条热门评论,下面再按时间顺序展示最新评论。这样既能满足用户查看受欢迎评论的需求,也能让他们及时了解最新的讨论。

面对大量评论数据,如何优化评论系统的加载速度

第一个是分页加载,对评论进行分类处理,避免一次性加载过多的评论,比如20条一页。

前端使用分页按钮和输入框跳转页码,每次只显示固定数量的评论

后端根据请求参数返回对应页码的评论数据

第二个就是使用redis来存储热门文章,例如站内hot100,并设置合理的缓存过期与更新机制来保证数据一致性。有点类似微博热搜的处理。

第三个是合理加mysql索引,比如对postid之类的常用字段添加索引,优化数据库查询

还有其他的方法,例如前端懒加载,只有滚动到评论区才加载。或者预加载之类的

发表评论

后才能评论