PSP2.1 | 開發流程 | 預估耗費時間(分鐘) | 實際耗費時間(分鐘) |
---|---|---|---|
Planning | 計劃 | 30 | 25 |
· Estimate | 明確需求和其餘相關因素,估計每一個階段的時間成本 | 10 | 20 |
Development | 開發 | 200 | 240 |
· Analysis | 需求分析 (包括學習新技術) | 20 | 20 |
· Design Spec | 生成設計文檔 | 10 | 15 |
· Design Review | 設計複審 | 10 | 45 |
· Coding Standard | 代碼規範 | 30 | 25 |
· Design | 具體設計 | 30 | 50 |
· Coding | 具體編碼 | 150 | 180 |
· Code Review | 代碼複審 | 10 | 15 |
· Test | 測試(自我測試,修改代碼,提交修改) | 30 | 55 |
Reporting | 報告 | 60 | 85 |
· | 測試報告 | 30 | 30 |
· | 計算工做量 | 30 | 25 |
· | 並提出過程改進計劃 | 30 | 15 |
關於此次的結對項目,咱們仔細閱讀並思考了題目的要求,明白了咱們要作的是:實現core模塊,實現詞組統計,實現自定義輸出以及程序的gui界面。html
core模塊
該功能的實現難點主要在於對用戶一行輸入參數的讀取分析,不一樣命令行參數能夠隨意組合。能夠考慮將輸入的命令行字符串進行分割,用字符串數組存儲每個字符,if判斷進行實現或用switch選擇結構進行實現。git
詞組統計
對於指定長度的詞組,咱們將文章中的單詞按序存儲(除去分割符),再根據用戶指定的長度,順序輸出對應的單詞數。正則表達式
gui界面
再將項目要求的功能基本實現後,進行gui編程,設計一個簡單便捷的圖形界面。編程
在實現過程當中,我與小夥伴主要設計了三個類,包括讀寫文件的FileFunction類,對單詞存儲、排序、輸出等操做的word類,以及完成輸入、輸出操做的Main函數。數組
Scanner sc = new Scanner(System.in); String file = null; int numM =0;\\詞組長度 int numN =0;\\輸出的單詞個數 String resultFile= null;\\生成文件路徑 String str = sc.nextLine(); String strarr[] = str.split("\\s+");\\空格分割字符串 List<String> list = new ArrayList<>(); for (String word:strarr) { list.add(word); } // 分析對應的命令參數並執行對應功能 for (int i = 0; i <list.size() ;i=i+2) { if (list.get(i).equals("-i")){ file = list.get(i+1); } if (list.get(i).equals("-m")){ numM = Integer.parseInt(list.get(i+1)); } if (list.get(i).equals("-n")){ numN = Integer.parseInt(list.get(i+1)); } if (list.get(i).equals("-o")){ resultFile = list.get(i+1); } }
二、詞組統計
當讀取用戶指定的詞組長度,就調用單詞操做類word中的Phrase函數。全局變量list即爲單詞表。字符串數組wordGroup用於存放詞組,數組長度爲詞組的數量(單詞表總數-詞組長度+1),利用雙重循環進行拼接單詞得到詞組。考慮到輸出的詞組應不重複,並統計詞組頻數,採用集合map進行操做,頻數爲value值。重寫Collections的sort函數將集合進行排序。函數
public String Phrase(int number) throws Exception{ if(number>lists.size()) { return "the number is too long"; } String wordGroup[] = new String[lists.size()-number+1]; for (int i = 0; i <lists.size()-number+1 ; i++) { String phrase = lists.get(i); for (int j = i+1; j <i+number ; j++) { phrase = phrase+" "+lists.get(j); } wordGroup[i] = phrase ; } Map<String,Integer> treeMap =new TreeMap<String,Integer>(); for (int i = 0; i < wordGroup.length; i++) { String s = wordGroup[i]; if (!treeMap.containsKey(s)) { //不存在該詞組,存入集合 treeMap.put(s, 1); } else { //存在將對應value加一 int n = treeMap.get(s); treeMap.put(s, n + 1); } } //統計詞組頻數 List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(treeMap.entrySet()); Collections.sort(list, ((o1, o2) -> o2.getValue().compareTo(o1.getValue()))); String s[] = new String[wordGroup.length]; int i =0; for (Map.Entry<String,Integer>entry:list) { String key = entry.getKey(); Integer value = entry.getValue(); s[i] = key + ": " + value; i++; } String string = s[0]+"\n"; for (int j = 1; j <i ; j++) { string = string + s[j] + "\n"; } return string ; }
三、自定義輸出
該功能與我的做業中的「統計詞頻並輸出頻數前10的單詞」有類似的地方。當對單詞完成存儲後,利用集合對全部單詞進行排序,最後再根據用戶指定的輸出單詞數n,按序輸出集合前n個單詞與詞頻。
sortWord函數中增長指定的輸出單詞數n,做爲傳入參數,便可完成自定義輸出。單元測試
public String sortWord(int number) throws Exception{ Map<String, Integer> treeMap = new TreeMap<String, Integer>(); for (int i = 0; i < lists.size(); i++) { String s = lists.get(i).toLowewerCase();//忽略大小寫 if (!treeMap.containsKey(s)) { //不存在,就存入集合中 treeMap.put(s, 1); } else { //存在就將value值加一 int n = treeMap.get(s); treeMap.put(s, n + 1); } } //單詞與頻數排序 List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(treeMap.entrySet()); Collections.sort(list, ((o1, o2) -> o2.getValue().compareTo(o1.getValue()))); // int n = 10; String s[] = new String[number]; int i =0; for (Map.Entry<String, Integer> entry : list) { if (number-- == 0) break; String key = entry.getKey(); Integer value = entry.getValue(); s[i] = "<" + key + ">:" + value; i++; }//拼接字符串 String string = s[0]+"\n"; for (int j = 1; j <i ; j++) { string =string+ s[j]+"\n"; } return string; }
public BufferedReader ReadFromFile(String path) throws IOException { //讀取文件 File file = new File(path); if (!file.exists() || file.isDirectory()) { System.out.println("文件路徑不存在"); throw new FileNotFoundException(); } InputStreamReader isr = new InputStreamReader(new FileInputStream(path)); BufferedReader br = new BufferedReader(isr); return br; } public void WriteToFile(String path,String content) throws Exception { //寫出文件 try { OutputStream out = new FileOutputStream(path); out.write(content.getBytes()); out.close(); } catch (Exception e) { e.printStackTrace(); } }
對於各個功能模塊分別提供一些測試樣例進行測試。學習
class FileFunctionTest { FileFunction fi=new FileFunction(); @Test void testReadFromFile() throws IOException { String path="input.txt"; assertTrue(fi.ReadFromFile(path).equals("Monday Tuesday Wednesday Thursday")); } @Test void testWriteToFile() throws Exception { String outpath="output.txt"; fi.WriteToFile(outpath, "hello i am test"); fi.ReadFromFile(outpath).equals( "hello i am test"); } }
測試截圖:
測試
在這次結隊過程當中,我收穫良多。與小夥伴一塊兒的結隊編程,帶來的不只是編程思想的對碰融合,更讓咱們在相互磨合、相互學習中深入體會到合做帶來的好處。咱們相互交流,相互學習,分享經驗。我看到了小夥伴與我徹底不同的思路和技能。在遇到不懂的地方我能獲得小夥伴的講解,增加知識。ui
審查題目要求,咱們重新增功能的要求入手。針對一個功能函數,咱們會先各自思考,闡述彼此的思路,說明這樣作的緣由和好處。哪個更好,咱們就採起哪個的。好比在討論詞組時,咱們一塊兒琢磨詞組的定義,進一步肯定獲取一個完整詞組的方法,再次基礎上,會琢磨如何根據用戶指定的詞組長度去得到一個完整詞組。當將基本設計思路肯定之後會開始動手編程,一我的先根據討論好的思路編程,另外一我的會在旁邊看着,注意她編程過程當中出現的如變量命名不規範的問題。當部分代碼的測試出現錯誤時,咱們會一塊兒尋找出錯緣由,並討論如何修改它。咱們發現,兩我的找錯的效律會大於一我的的效律。同時咱們會在實現過程當中提出一些改進的意見和建議。好比對用戶輸入的詞組長度的判斷處理,在設計時沒有考慮到當詞組長度大於單詞總數的狀況,實現的時提了出來,恍然大悟應該注意到這種狀況。當沒法繼續編程下去的時候,咱們會互換角色。總之,咱們在結對合做的過程當中彼此受益。