天天看點

福大軟工1816 · 第二次作業-個人項目

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詞頻表的建立
    福大軟工1816 · 第二次作業-個人項目

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.性能分析

福大軟工1816 · 第二次作業-個人項目
福大軟工1816 · 第二次作業-個人項目

以下主要是調用各個不同類中的接口,是以Main中的覆寫率會為0,整體的情況符合正常的操作結果。

福大軟工1816 · 第二次作業-個人項目
福大軟工1816 · 第二次作業-個人項目

進行單元測試的過程中,可通過如下的報錯來尋找自己的疏漏之處,每一環節都能夠很好的定位到。

福大軟工1816 · 第二次作業-個人項目

Part7.感想

有了初步的構思以後,邊學習邊敲java代碼,實踐中去逐漸的完善自己,總體來說,我對自己的表現還是挺滿意的。過程中接觸了單元測試,找到了自己許多原先疏漏的小細節,在逐漸改進之下完善着自己的代碼。怎麼說呢,可能還是自己的慢性子的原因,每天都在投入時間去邊敲邊改,但是很遺憾,得出最終成果的時間還是壓到了接近與deadline之前一些些,是以我對自己下一次任務的期望是自己能夠有更高的效率,達到更好的效果,以上。

福大軟工1816 · 第二次作業-個人項目

也希望大家能夠對我提出寶貴的意見,謝謝大家,小廢的程式員之路道阻且長......

Part8.後記

後續在完成作業以後,看到了許多同學都有意識的去讨論測試資料的大小問題,是以自己也做了一下大型文本的測試,果然發現出錯。總結一下自己得出的結論:String對于連接配接操作(“+”)效率很低,是以導緻了我程式一直沒辦法正常運作,後改用StringBuilder,利用.append()方法來進行文本的逐行拼接,成功解決了上述所困擾我的問題。(更新代碼内容詳見github源碼部分),後續将會對為什麼String效率低的問題分析好後作出解釋,暫告一段落,謝謝(附上大型資料測試情況)

這裡簡單的結合office word自帶的字數統計功能校驗如下:

福大軟工1816 · 第二次作業-個人項目