我们有一个简单的需求:
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>3.7.0</version> <!-- 使用你需要的版本 -->
</dependency>
</dependencies>
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Tuple;
import java.util.Set;
import java.util.HashSet;
import java.util.List;
import java.util.ArrayList;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
public class HotSearch {
private static final String REDIS_HOST = "localhost";
private static final int REDIS_PORT = 6379;
private static final String HISTORY_SET = "history";
private static final String ZSET_PREFIX = "zset:";
private static final int TOP_TEN = 10;
private static final String BAD_WORDS = "bad"; // 替换为需要过滤的关键词
private static final String FILTERED_WORD = "***"; // 替换为过滤后的关键词
private static final int BAD_WORD_THRESHOLD = 100; // 替换为过滤的阈值,超过则认为是不雅文字
private static final List<String> BAD_WORD_LIST = IntStream.range(0, BAD_WORDS.length()).mapToObj(i -> BAD_WORDS.substring(i, i + 1)).collect(Collectors.toList()); // 将BAD_WORDS转为List,方便后续操作
public static void main(String[] args) {
Jedis jedis = new Jedis(REDIS_HOST, REDIS_PORT);
String userId = "user1"; // 当前登陆的个人用户ID,需要根据实际情况获取
String searchWord = "test"; // 需要搜索的字符
hotSearch(jedis, userId, searchWord);
}
public static void hotSearch(Jedis jedis, String userId, String searchWord) {
// 获取当前用户的搜索历史记录
Set<String> history = jedis.smembers(HISTORY_SET + ":" + userId);
if (history == null) history = new HashSet<>();
history.add(searchWord); // 将新搜索词加入历史记录
jedis.sadd(HISTORY_SET + ":" + userId, history); // 将历史记录存入redis中
history.remove(searchWord); // 去掉新搜索词,只保留旧的历史记录
// 将搜索词加入zset中,记录该字符被搜索的个数以及当前的时间戳
jedis.zadd(ZSET_PREFIX + userId, getScore(searchWord), searchWord);
System.out.println("Added " + searchWord + " to hot search with score " + getScore(searchWord));
// 过滤不雅文字,如果是不雅文字则替换为***,并累加不雅文字的搜索次数
if (BAD_WORD_LIST.contains(searchWord)) {
if (jedis.zscore(ZSET_PREFIX + userId, FILTERED_WORD) == null) { // 如果该词在zset中不存在,则加入并设置得分
jedis.zadd(ZSET_PREFIX + userId, BAD_WORD_THRESHOLD, FILTERED_WORD); // 设置得分为BAD_WORD_THRESHOLD,表示这是一个不雅文字
jedis.incrBy(HISTORY_SET + ":bad", 1); // 累加不雅文字的搜索次数,存储在bad历史的集合中,方便后续统计和过滤处理
} else { // 如果该词在zset中已存在,则只累加搜索次数,并更新得分(得分+1)
jedis.zincrby(ZSET_PREFIX + userId, 1, FILTERED_WORD); // 得分为当前得分+1,表示这是一个不雅文字的再次搜索
jedis.incrBy(HISTORY_SET + ":bad", 1); // 累加不雅文字的搜索次数,存储在bad历史的集合中,方便后续统计和过滤处理
}
System.out.println("The word " + searchWord + " is filtered and replaced with " + FILTERED_WORD); // 输出过滤后的结果
} else { // 如果不是不雅文字,则正常加入热搜列表并设置得分
jedis.zadd(ZSET_PREFIX + userId, getScore(searchWord), searchWord); // 正常加入热搜列表并设置得分
System.out.println("Added normal word " + searchWord + " to hot search with score " + getScore(searchWord)); // 输出正常加入热搜列表的结果
}
// 获取平台上最热搜索的十条数据
Set<Tuple> hotData = jedis.zrevrangeWithScores(ZSET_PREFIX + userId, 0, TOP_TEN - 1);
List<String> hotWords = hotData.stream().map(Tuple::getElement).collect(Collectors.toList());
List<Integer> hotScores = hotData.stream().map(Tuple::getScore).collect(Collectors.toList());
System.out.println("Top " + TOP_TEN + " hot searches are: " + hotWords + " with scores: " + hotScores);
}
// 用于计算得分的方法,这里采用了最简单的得分方式,只考虑了搜索频率和时间戳,实际情况可能需要更复杂的算法
private static int getScore(String word) {
return 1;
}
}
HISTORY_SET + ":" + userId
来区分不同用户的搜索历史。jedis.sadd
方法用于添加新搜索词到历史记录集合中。jedis.srem
方法从集合中移除某个元素来实现。ZSET_PREFIX + userId
来区分不同用户的热搜数据。getScore
计算得出。新搜索词得分为1,旧搜索词得分为0。这个得分代表了搜索的频率和时间戳。jedis.zadd
方法用于向有序集合中添加新元素,并设置其得分。jedis.zrevrangeWithScores
方法获取有序集合中的前十个元素(得分最高的十个搜索词)。BAD_WORDS
列表中。BAD_WORD_THRESHOLD
,则认为这是一个不雅文字,将其替换为FILTERED_WORD
。