以下代码提供了一个类的简单版本,它跟踪字符串的输入频率(方法addPV),并且可以按顺序输出具有最高计数的k个字符串(方法firstK)。
在下面的简化代码中,二进制搜索树(treeset)用于跟踪计数并保持顺序。辅助数据结构(hashmap)用于快速访问treeset中的元素。使用包含字符串名称和计数的复合条目类,其中count确定自然顺序和hashCode的名称。
最优雅的方法是使用 BST(例如树形图),其条目将计数作为键,字符串名称作为值。内部散列映射可用于在恒定时间内有效地访问BST中的条目。普通库中是否有标准数据结构来执行常规对象?
import java.util.*;
public class MostVisitedPages {
private HashMap<String,CountEntry> hm = new HashMap<>();
private TreeSet<CountEntry> ts = new TreeSet<>();
private static class CountEntry implements Comparable<CountEntry>{
String page;
int count;
CountEntry (String page, int count){
this.page = page;
this.count = count;
}
@Override
public int compareTo(CountEntry entry){
int res = Integer.compare(count,entry.count);
return res != 0 ? res: page.compareTo(entry.page);
}
@Override
public boolean equals(Object obj){
if(this == obj) return true;
else if (obj==null || !(obj instanceof CountEntry)) return false;
else {return page.equals(((CountEntry)obj).page);}
}
@Override
public int hashCode(){
return page.hashCode();
}
}
public void addPV(String p){
if(hm.containsKey(p)){
CountEntry ce = hm.get(p);
ts.remove(ce);
ce.count += 1;
ts.add(ce);
} else {
CountEntry ce = new CountEntry(p,1);
ts.add(ce);
hm.put(p, ce);
}
}
public List<String> firstK(int k){
List<String> ret = new ArrayList<>(k);
Iterator<CountEntry> it = ts.descendingIterator();
for(int i = 0; i<k && i<hm.size(); i++){
ret.add(it.next().page);
}
return ret;
}
}