今天做了一個功能,要在每個帖子的標簽中選出最熱門的幾個標簽。
想了一下,這不就topn嗎,雖然算法不咋地,但現(xiàn)學現(xiàn)賣還是可以滴
用了前面寫過的定時器,還有java的優(yōu)先級隊列
java中PriorityQueue通過小頂堆實現(xiàn),要用它進行比較的話得實現(xiàn)Comparable接口,重寫其中的compareTo方法。
@Data
public class HotTagDTO implements Comparable{
private String name;
private Integer priority;
@Override
public int compareTo(Object o) {
return this.getPriority() - ((HotTagDTO) o).getPriority();
}
}
然后呢,實現(xiàn)其實有幾種方式,比如說
- 遍歷所有帖子,然后,取出每個帖子的標簽
- 對每個標簽,遍歷含有它的帖子
但要考慮的是,可能標簽有很多,但有的標簽用不上;一個帖子可能含有多個標簽
所以第二種方法時間復雜度就有點高了
另外,熱門如何定義呢?
其實就可以自定義一個優(yōu)先級計算公式,比如說加權求和。我覺得對一個標簽影響比較大的是帖子數(shù)量和相應的回復數(shù),所以我就可以根據(jù)這兩個來求優(yōu)先級
首先用ArrayList來放所有帖子
List<Question> list = new ArrayList<>();
然后遍歷獲取標簽,標簽是用逗號分隔開的
優(yōu)先級就暫且設置帖子數(shù)權重為5,帖子回復數(shù)權重為1
每個標簽的優(yōu)先級用一個hashmap來存放
Map<String, Integer> priorities = new HashMap<>();
for (Question question : list) {
String[] tags = StringUtils.split(question.getTag(), ",");
for (String tag : tags) {
Integer priority = priorities.get(tag);
if (priority != null) {
priorities.put(tag, priority + 5 + question.getCommentCount());
} else {
priorities.put(tag, 5 + question.getCommentCount());
}
}
}
用PriorityQueue獲取topn
PriorityQueue<HotTagDTO> priorityQueue = new PriorityQueue<>(10);
流程如下,先把前n個結果放入優(yōu)先級隊列中,這之后,因為重寫了compareTo方法,所以可以比較大小,若優(yōu)先級小于PriorityQueue中最小的,直接跳過,否則就覆蓋根節(jié)點,并重排小頂堆。這樣就得到了優(yōu)先級最高的n個標簽。
在任務上加上@Scheduled(fixedRate = 1000 * 60 * 60 * 12)注解,就能實現(xiàn)每12小時進行一次更新。