Part 1.卷首語
github傳送門
本次的開發環境
- Windows 10 64bit + Eclipse + JProfiler
Part 2.PSP表格
PSP2.1 | Personal Software Process Stages | 預估耗時(分鐘) | 實際耗時(分鐘) |
---|---|---|---|
Planning | 計劃 | --- | |
· Estimate | · 估計這個任務需要多少時間 | 10 | 20 |
Development | 開發 | ||
· Analysis | · 需求分析 (包括學習新技術) | 120 | 150 |
· Design Spec | · 生成設計文檔 | 30 | |
· Design Review | · 設計複審 | ||
· Coding Standard | · 代碼規範 (為目前的開發制定合适的規範) | ||
· Design | · 具體設計 | 60 | 40 |
· Coding | · 具體編碼 | 700 | 1320 |
· Code Review | · 代碼複審 | ||
· Test | · 測試(自我測試,修改代碼,送出修改) | ||
Reporting | 報告 | ||
· Test Repor | · 測試報告 | ||
· Size Measurement | · 計算工作量 | ||
· Postmortem & Process Improvement Plan | · 事後總結, 并提出過程改進計劃 | ||
合計 | 1080 | 1830 |
Part 3.解題思路
首先問題的大緻要求是需要統計文本中的各參數數量與詞頻,整體的先後思路如下:
- 1.首先要做的事情就是将.txt中的文本轉換為可操作的字元串(結果還需要寫入.txt檔案中),這個過程關系到檔案流操作;
- 2.對于可操作的字元串,要對其進行篩選、轉化、切割、選擇(開頭4個字母後含若幹個字母數字的形式);
- 3.對于處理後的單詞集,需要對其進行詞頻統計,并在統計結束後排序好先後順序傳回主函數,基本任務完成。
Part 4.實作過程
- countChar:負責字元數的統計;
- countVec:負責單詞數的統計;
- countLine:負責行數的統計;
- createMap:負責處理HashMap詞頻表的建立
Part5.關鍵代碼展示
簡單的列出主要花費自己心思去寫的兩部分代碼,其餘的詳細請見github上的源碼。
對于單詞的選擇,我主要利用的是正則比對的方式來選擇,先将内部不符合的元素用某一符号代替,而這一符号将作為下一次分隔符标志,利用Pattern和Matcher去除非英文數字字元,而後進一步對單詞的樣式進行限制,對于符合正規表達式的單詞加入清單中提供給後續使用
public static int countwords(int count,String text){
list.clear(); //做初始化清空字元集處理
String regex ="[^0-9a-zA-Z]"; //剔除文本中的非字母和數字的部分并以!作為暫時的分隔符
Pattern pat = Pattern.compile(regex);
Matcher mat = pat.matcher(text);
text = mat.replaceAll("!");
String [] textArray = text.split("!+"); //按照分隔符劃分
String v_regex = "^[a-z]{4}[a-z0-9]*$"; //對單詞形式進行約定
for(String i:textArray){
Pattern v_pat = Pattern.compile(v_regex);
Matcher v_mat = v_pat.matcher(i);
if(v_mat.matches())
list.add(i);
}
return list.size();
}
對于詞頻分類和統計,這裡利用了HashMap,簡單且易查找,<Key,Value>的形式很好的記錄了<單詞本身,出現次數>這樣的記錄。最後将記錄好的Map進行排序,按照題給要求,先以Value值做參考,在Value值相同的情況下,以Key值優先為準。
public static List<Map.Entry<String,Integer>> createHashMap(List<String>list){
Map<String,Integer> ver = new HashMap<String, Integer>();
for(String i:list){
if(!ver.containsKey(i))
ver.put(i, 1);
else{
Integer num = ver.get(i);
ver.put(i, num+1);
}
}
List<Map.Entry<String,Integer>> verlist = new ArrayList<Map.Entry<String,Integer>>(ver.entrySet());
Collections.sort(verlist,new Comparator<Map.Entry<String, Integer>>(){
public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {
if(o1.getValue()==o2.getValue()){
return (o1.getKey()).compareTo(o2.getKey());
}
return o2.getValue()-o1.getValue();
}
});
return verlist;
}
下面主要是我對于IO操作的異常進行處理的基本形式
public static int countChar(String path,int count) throws IOException{
try {
...
} catch (FileNotFoundException e) {
e.printStackTrace();
}finally{
...
}
return count;
}
Part6.性能分析
以下主要是調用各個不同類中的接口,是以Main中的覆寫率會為0,整體的情況符合正常的操作結果。
進行單元測試的過程中,可通過如下的報錯來尋找自己的疏漏之處,每一環節都能夠很好的定位到。
Part7.感想
有了初步的構思以後,邊學習邊敲java代碼,實踐中去逐漸的完善自己,總體來說,我對自己的表現還是挺滿意的。過程中接觸了單元測試,找到了自己許多原先疏漏的小細節,在逐漸改進之下完善着自己的代碼。怎麼說呢,可能還是自己的慢性子的原因,每天都在投入時間去邊敲邊改,但是很遺憾,得出最終成果的時間還是壓到了接近與deadline之前一些些,是以我對自己下一次任務的期望是自己能夠有更高的效率,達到更好的效果,以上。
也希望大家能夠對我提出寶貴的意見,謝謝大家,小廢的程式員之路道阻且長......
Part8.後記
後續在完成作業以後,看到了許多同學都有意識的去讨論測試資料的大小問題,是以自己也做了一下大型文本的測試,果然發現出錯。總結一下自己得出的結論:String對于連接配接操作(“+”)效率很低,是以導緻了我程式一直沒辦法正常運作,後改用StringBuilder,利用.append()方法來進行文本的逐行拼接,成功解決了上述所困擾我的問題。(更新代碼内容詳見github源碼部分),後續将會對為什麼String效率低的問題分析好後作出解釋,暫告一段落,謝謝(附上大型資料測試情況)
這裡簡單的結合office word自帶的字數統計功能校驗如下: