20180912-3 词频统计
作业要求 20180912-3 词频统计
该作业的要求参见:https://edu.cnblogs.com/campus/nenu/2019fall/homework/6583
源码地址:https://e.coding.net/SpringSun/Statisticalword.git
一、准备工作
看题目大概读了一遍感觉好复杂,完全没有思路,就一个字难。而且里面专有名词不知道,像“代码要求在 coding.net 做版本控制。要求push&pull时使用git客户端,不允许使用web页面”。不明白版本控制是什么?git客户端又是什么?然后去百度了一下。
二、弄懂概念
版本控制是指对软件开发过程中各种程序代码、配置文件及说明文档等文件变更的管理,是软件配置管理的核心思想之一。
Git是一个开源的分布式版本控制系统,用以有效、高速的处理从很小到非常大的项目版本管理。
三、下载软件
第一步: 申请coding.net账号并新建一个项目。
coding.net代码托管平台使用教程:https://blog.51cto.com/net881004/2068431
第二步:下载、安装git和git客户端tortoisgit。
git下载地址:https://git-scm.com/download
tortoisgit下载地址:https://tortoisegit.org/download/
第三步:在coding.net上配置远程git ,具体请参见
https://blog.csdn.net/gyy930324/article/details/54575246
coding.net及git的使用方式可参考: https://www.cnblogs.com/life-for-test/p/6284041.html
(ps平时编辑文档养成好习惯,文档做完就保存一下,要不忘记保存,还找不回来,真是心累,这次真是学乖了,以后打死都要记得保存文档)
四、功能实现的历程
功能1 小文件输入。 为表明程序能跑,结果真实而不是迫害老五,请他亲自键
盘在控制台下输入命令。
为了评估老五的词汇量而不是阅读量,total一项中相同的单词不重复计数数,出现2
次的very计数1次。
因为用过控制台和命令行,你早就知道,上面的">"叫做命令提示符,是操作系统的一部分,而不是你的程序的一部分。
此功能完成后你的经验值+10.
重要代码:
//单行统计 public static void LineCount(String args) { String[] wordsArr = args.split("[^a-zA-Z]"); //过滤掉除字母以外的字符 List<String> list = new ArrayList<String>(); //存储过滤后单词的列表 for (String word : wordsArr) { if (word.length() != 0) { //去除长度为0的行 list.add(word); } } WordCount(list); // 单词量统计 }
控制台截屏:
功能2 支持命令行输入英文作品的文件名,请老五亲自录入。
此功能完成后你的经验值+30. 输入文件最大不超过40MB. 如果你的程序中途崩
了,会被老五打脸,不增加经验值。
重要代码:
// 单文件统计 public static void textCount(String path) throws Exception { BufferedReader br = new BufferedReader(new FileReader(path)); List<String> list = new ArrayList<String>(); // 存储过滤后单词的列表 String sLine = null; while ((sLine = br.readLine()) != null) { String[] wordsArr = sLine.split("[^a-zA-Z]"); // 过滤掉除字母以外的字符 for (String word : wordsArr) { if (word.length() != 0) { // 去除长度为0的行 list.add(word); } } } br.close(); WordCount(list); // 单词量统计 }
控制台截屏:
功能3 支持命令行输入存储有英文作品文件的目录名,批量统计。
重要代码:
//多文件统计 String path1 = args[1]; File file = new File(path1); if (file.isDirectory()) { File[] filelist = file.listFiles(); for (File filePath : filelist) { try { String s = filePath.getPath();// 获取完整路径 System.out.println(filePath.getName());//输出文件名 textCount(s); } catch (Exception ex) { System.out.println("请输入正确的路径,格式:D:/Project/JAVA/text/"); } } }
控制台截屏:
功能4 从控制台读入英文单篇作品,这不是为了打脸老五,而是为了向你女朋
友炫酷,表明你能提供更适合嵌入脚本中的作品(或者如她所说,不过是更灵活
的接口)。如果读不懂需求,请教师兄师姐,或者 bing: linux 重定向,尽管
这个功能在windows下也有,搜索关键词中加入linux有利于迅速找到。
重要代码:
//重定向单个文件统计 public static void TxtCount() throws Exception { BufferedReader br = new BufferedReader(new InputStreamReader(System.in));//从字符输入流中读取文本并缓冲字符 //BufferedReader br = new BufferedReader(new FileReader("D:/Project/JAVA/text/" + "test.txt"));//eclipse测试用 List<String> list = new ArrayList<String>(); //存储过滤后单词的列表 String readLine = null; while ((readLine = br.readLine()) != null) { String[] wordsArr1 = readLine.split("[^a-zA-Z]"); //过滤掉除字母以外的字符 for (String word : wordsArr1) { if (word.length() != 0) { //去除长度为0的行 list.add(word); } } } br.close(); WordCount(list); // 单词量统计 }
控制台截屏:
重要单词计数代码:
// 单词量统计 public static void WordCount(List<String> list) { Map<String, Integer> wordsCount = new TreeMap<String, Integer>(); // 存储单词计数信息,key值为单词,value为单词重复数 // 单词的重复数统计 for (String i : list) { if (wordsCount.get(i) != null) { wordsCount.put(i, wordsCount.get(i) + 1); } else { wordsCount.put(i, 1); } } System.out.println("------------------------"); //System.out.println("words_total" + " " + list.size() + " words");// 输出单词总量 System.out.println("total" + " " + wordsCount.size() + " words\n");// 输出单词量 SortMap(wordsCount); // 按值进行排序 System.out.println("-------------------------------------"); }
重要排序代码:
//按值大小降序处理 public static void SortMap(Map<String, Integer> oldmap) { ArrayList<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(oldmap.entrySet()); Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() { public int compare(Entry<String, Integer> o1,Entry<String, Integer> o2) { return o2.getValue() - o1.getValue(); // 降序 } }); if (list.size()<10){ for (int i = 0; i < list.size(); i++) {// 因为text.txt文本只有5个单词量,加if条件防止循环不到10次报错 System.out.println(list.get(i).getKey() + " " + list.get(i).getValue());// 输出单词和重复数 } }else { for (int i = 0; i < 10; i++) {// 便于截图只显示10行,全部显示把10替换成list.size() System.out.println(list.get(i).getKey() + " " + list.get(i).getValue());// 输出单词和重复数 } } }
在所有功能实现前,我思考了好久,应该怎样下手,可是想了半天,就选择那门语言,想选择C语言,可是感觉题目功能也不少,要是用C语言,工程可能会大,而java是面向对象的,实现起来应该会简单一些,然而java自己已经忘的差不多了,打算先把java 学习一遍在开始编程,可是师兄看到我一直在看书,建议我一边学一边写,只有在实践中才能知道那些知识要用到,而且效率高,所以整个工程都是在边写边学中进行的。
功能一:
- 忘记怎么输入一串字符,按空格取每个单词的操作,所以复习了谭浩强的《C语言程序设计》。
- 忘记正则表达式,查了正则表达式的写法
- 查了java 中列表怎样定义
功能二:
在控制台里输入一个文件名然后读取文件里的内容,格式和表达式的书写。
功能三:
一开始感觉功能二和功能三是一样的,后来仔细读了作业要求,功能二和功能三差在了是读一个文件还是多个(个人理解),所以在写功能三就把读入一个文件格式去掉了。
功能四:
一开始功能四就没有看懂,尤其是上面功能二和功能三都感觉一样,这个功能四简直了,我打算先把前三个功能先实现,时间允许的情况下,在来搞功能四。
知识链接:
一开始三个功能完成后,总是感觉少了什么,运行程序才发现少了排序,排序就想到了使用HashMap还是TreeMap,两者区别:HashMap通过hashcode对其内容进行快速查找,而 TreeMap中所有的元素都保持着某种固定的顺序,如果你需要得到一个有序的结果你就应该使用TreeMap(HashMap中元素的排列顺序是不固定的)。
五、程序PSP分析
PSP阶段 |
预计花费时间 |
实际花费时间 |
时间差值 |
差距原因分析 |
功能一 |
120 |
303 |
177 |
忘记怎么输入一串字符,按空格取每个单词的操作 |
功能一测试 |
30 |
56 |
26 |
这个没有统计总字数,所以老出错 |
功能二 |
30 |
49 |
19 |
在控制台里输入一个文件名然后读取文件里的内容,格式和表达式的书写忘记怎么写 |
功能二测试 |
10 |
24 |
14 |
不能统计全文 |
功能三 |
20 |
55 |
35 |
多个文件输入问题处理模糊 |
功能三测试 |
20 |
36 |
16 |
读入多个文件怎么读入 |
功能四 |
30 |
39 |
9 |
这个时间是不完美程序时间 |
功能四测试 |
50 |
180 |
130 |
不能同时读入多个文件 |