第4周小组作业:WordCount优化
Github项目地址:https://github.com/chaseMengdi/wcPro
stage1:代码编写+单元测试
PSP表格
PSP2.1 |
PSP阶段 |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
25 |
30 |
Estimate |
估计任务需要多少时间 |
25 |
30 |
Development |
开发 |
300 |
302 |
Analysis |
需求分析 |
20 |
20 |
Design Spec |
生成设计文档 |
20 |
15 |
Design Review |
设计复审 |
20 |
15 |
Coding Standard |
代码规范 |
20 |
15 |
Design |
具体设计 |
20 |
25 |
Coding |
具体编码 |
90 |
80 |
Code Review |
代码复审 |
20 |
30 |
Test |
测试 |
60 |
80 |
Reporting |
报告 |
80 |
95 |
Test Report |
测试报告 |
30 |
50 |
Size Measurement |
计算工作量 |
30 |
25 |
Postmortem |
总结 |
20 |
20 |
合计 |
405 |
430 |
描述代码设计思路
接口设计
public static HashMap<String, Integer> count(String thefile)
划分统计单词数
接口实现
count()函数传入的是一个文件名,即txt文件名,通过逐行读取文件,先将字符串转换为小写,通过split()函数对字符串进行划分。个人技术有限,发现当字符串的最前面的字符是非字母的时候,split()划分会出现不知名的空,故在使用split()进行划分前需要先去掉字符串最前面的非字母字符,同时还有注意“-”出现的情况,如—word-word---,---,需要去开头的“-”和结尾的“-”,而保留词与词间的“-”。然后进行单词统计,将结果存放在HashMap<String, Integer>中。
// 划分统计单词数public static HashMap<String, Integer> count(String thefile) {File file = new File(thefile);HashMap<String, Integer> map = new HashMap<>();if (file.exists()) {try {FileInputStream fis = new FileInputStream(file);InputStreamReader isr = new InputStreamReader(fis, "UTF-8");BufferedReader br = new BufferedReader(isr);String line = new String("");StringBuffer sb = new StringBuffer();while ((line = br.readLine()) != null) {// 转为小写 line = line.toLowerCase();int k = 0;// 去除行首的非字母单词char first = line.charAt(k);while (!((first >= 'a' && first <= 'z') || first == '-')) {k++;first = line.charAt(k);}line = line.substring(k);// 去除多个空格\\s+ String[] split = line.split("\\s++|0|1|2|3|4|5|6|7|8|9|\\_|\\'|\\.|\\,|\\;|\\(|\\)|\\~|\\!|"+ "\\@|\\#|\\$|\\%|\\&|\\*|\\?|\""+ "|\\[|\\]|\\<|\\>|\\=|\\+|\\*|\\/|\\{|\\}|\\:|\\||\\^|\\`");for (int i = 0; i < split.length; i++) {// 获取到每一个单词 Integer integer = map.get(split[i]);// 考虑末尾为-的单词或开头为---if ((split[i].endsWith("-") || split[i].startsWith("-"))&& !(split[i].equals("-"))) {// 去除多个空格\\s+ String[] sp = split[i].split("\\s++|\\-");// 全部为----if (sp.length == 0) {split[i] = "-";integer = map.get(split[i]);}// 处理--danelse if (split[i].startsWith("-")) {int j = 0;char si = split[i].charAt(0);while (split[i].charAt(j) == si)j++;split[i] = split[i].substring(j);integer = map.get(split[i]);}// 去除多个空格\\s+ sp = split[i].split("\\s+|\\-");// 全部为----if (sp.length == 0) {split[i] = "-";integer = map.get(split[i]);}// 处理dn-dan---else {String tmp = sp[0];for (int j = 1; j < sp.length; j++) {tmp = tmp + "-" + sp[j];}split[i] = tmp;integer = map.get(split[i]);}}if (!split[i].equals("") && !split[i].equals("-")) {// 如果这个单词在map中没有,赋值1if (null == integer) {map.put(split[i], 1);} else {// 如果有,在原来的个数上加上一 map.put(split[i], ++integer);}}}}sb.append(line);br.close();isr.close();fis.close();} catch (FileNotFoundException e) {e.printStackTrace();} catch (UnsupportedEncodingException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}} else {System.out.print("文件不存在\n");}return map;}
测试设计过程
count()函数的测试设计应以黑盒设计为主,首先创建并初始化一个HashMap<String, Integer>和txt文件,随后将txt文件名传入count(),将实际输出与期望输出利用断言进行对比。
20个测试用例设计如下:
Test Case ID 测试用例编号 |
Test Item 测试项(即功能模块或函数) |
Test Case Title 测试用例标题 |
Test Criticality 重要级别 |
Pre-condition 预置条件 |
Input 输入 |
Output 预期结果 Result |
Status |
Remark 备注 |
count_01 |
划分统计单词数 |
一个单词,小写 |
L |
txt文件存在 |
01.txt |
单词与词频 |
OK |
黑盒测试 |
count_02 |
划分统计单词数 |
多个单词,小写 |
L |
txt文件存在 |
02.txt |
单词与词频 |
OK |
黑盒测试 |
count_03 |
划分统计单词数 |
一个单词,大小写混合 |
L |
txt文件存在 |
03.txt |
单词与词频 |
OK |
黑盒测试 |
count_04 |
划分统计单词数 |
多个单词,大小写混合 |
L |
txt文件存在 |
04.txt |
单词与词频 |
OK |
黑盒测试 |
count_05 |
划分统计单词数 |
一个单词,大小写+连字符混合 |
L |
txt文件存在 |
05.txt |
单词与词频 |
OK |
黑盒测试 |
count_06 |
划分统计单词数 |
多个单词,大小写+连字符混合 |
L |
txt文件存在 |
06.txt |
单词与词频 |
OK |
黑盒测试 |
count_07 |
划分统计单词数 |
一个单词,大小写+连字符(任意位置)混合 |
L |
txt文件存在 |
07.txt |
单词与词频 |
OK |
黑盒测试 |
count_08 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)混合 |
L |
txt文件存在 |
08.txt |
单词与词频 |
OK |
黑盒测试 |
count_09 |
划分统计单词数 |
一个单词,大小写+单引号混合 |
L |
txt文件存在 |
09.txt |
单词与词频 |
OK |
黑盒测试 |
count_10 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号混合 |
L |
txt文件存在 |
10.txt |
单词与词频 |
OK |
黑盒测试 |
count_11 |
划分统计单词数 |
一个单词,大小写+连字符+双引号混合 |
L |
txt文件存在 |
11.txt |
单词与词频 |
OK |
黑盒测试 |
count_12 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号+双引号混合 |
L |
txt文件存在 |
12.txt |
单词与词频 |
OK |
黑盒测试 |
count_13 |
划分统计单词数 |
一个单词,大小写+连字符(任意位置)+双引号+数字混合 |
M |
txt文件存在 |
13.txt |
单词与词频 |
OK |
黑盒测试 |
count_14 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号+双引号+数字混合 |
M |
txt文件存在 |
14.txt |
单词与词频 |
OK |
黑盒测试 |
count_15 |
划分统计单词数 |
一个单词,大小写+连字符(任意位置)+双引号+数字(任意位置)混合 |
M |
txt文件存在 |
15.txt |
单词与词频 |
OK |
黑盒测试 |
count_16 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号+双引号+数字(任意位置)混合 |
M |
txt文件存在 |
16.txt |
单词与词频 |
OK |
黑盒测试 |
count_17 |
划分统计单词数 |
一个单词,大小写+连字符(任意位置)+双引号+数字(任意位置)+常见符号混合 |
M |
txt文件存在 |
17.txt |
单词与词频 |
OK |
黑盒测试 |
count_18 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号+双引号+数字(任意位置)+常见符号混合 |
H |
txt文件存在 |
18.txt |
单词与词频 |
OK |
黑盒测试 |
count_19 |
划分统计单词数 |
一个单词,大小写+连字符(任意位置)+双引号+数字(任意位置)+常见符号混合 |
H |
txt文件存在 |
19.txt |
单词与词频 |
OK |
黑盒测试 |
count_20 |
划分统计单词数 |
多个单词,大小写+连字符(任意位置)+单引号+双引号+数字(任意位置)+常见符号+词频相同混合 |
H |
txt文件存在 |
20.txt |
单词与词频 |
OK |
黑盒测试 |
测试运行和评价
count(String thefile)的单元测试的数据量和复杂度逐渐增加,符合测试用例设计规范,所有单元测试均通过。
count(String thefile)函数质量水平较高,可以正常的划分字符串和统计单词。
小组贡献
我负责的是划分统计单词数,这是本程序流程的第二步,如果出现错误,将会引起连锁反应致使本程序不能正确运行,所以这部分的正确性是很重要。
刚开始用split()对字符串进行分割,但后来发现如果字符串的开始部分是分割字符将会导致分割到的第一个字符串为空(不知道为什么),故本人加入一个去除以非字母开始的字符直到出现第一个字母。由于出现“-”的单词有几种情况,还需要对它们进行判断处理。
我个人的代码行数占了0.51,主要是要求有点多,需要考虑的情况较多,个人觉得应该还是完成的挺不错的.
stage2:静态测试
开发规范理解
《阿里巴巴Java开发手册》中指出:
2. 【强制】代码中的命名严禁使用拼音与英文混合的方式,更不允许直接使用中文的方式。 说明:正确的英文拼写和语法可以让阅读者易于理解,避免歧义。注意,即使纯拼音命名方式也要避免采用。
正例:alibaba / taobao / youku / hangzhou 等国际通用的名称,可视同英文。
反例:DaZhePromotion [打折] / getPingfenByName() [评分] / int 某变量 = 3
理解:
我觉得这点规定非常好,因为正确的英文拼写和语法可以让阅读者易于理解,避免歧义。而拼音英文混合和中文命名代码的方式则不利于读者阅读代码,也不利于性能优化和同行评审。我负责的单词统计模块代码命名均为国机通用的英文,符合《阿里巴巴Java开发手册》第二条的强制规定。
组员代码评价
选择刘博谦(17070)的代码进行分析
// 词频排序public static ArrayList<String> sort(HashMap<String, Integer> map) {// 以Key进行排序TreeMap treemap = new TreeMap(map);// 以value进行排序ArrayList<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(treemap.entrySet());Collections.sort(list, new Comparator<Map.Entry<String, Integer>>() {public int compare(Map.Entry<String, Integer> o1,Map.Entry<String, Integer> o2) {// 降序return o2.getValue() - o1.getValue();// 升序 o1.getValue() - o2.getValue()) }});ArrayList<String> str = new ArrayList<String>();int i = 0;for (Map.Entry<String, Integer> string : list) {// 排除-与空格if (!(string.getKey().equals("")) && !(string.getKey().equals("-"))) {str.add(string.getKey());str.add(string.getValue().toString());// 输出前1000个单词if (i > 1000)break;i++;}}return str;}
刘博谦的代码遵守了《阿里巴巴Java开发手册》第二条的强制规定,代码命名规范,无需改进。
静态代码检查
选择工具:FindBugs 3.0.1
下载链接:http://findbugs.sourceforge.net/
检查结果如下:
String line = new String("");
缺陷信息:
Method invokes inefficient new String(String) constructor
Using the java.lang.String(String)
constructor wastes memory because the object so constructed will be functionally indistinguishable from the String
passed as a parameter. Just use the argument String
directly.
Bug kind and pattern: Dm - DM_STRING_CTOR
分析:new String("")构造函数效率低,直接line=""即可。
个人代码改进
个人代码符合《阿里巴巴Java开发手册》第二条的强制规定,改正FindBugs指出的缺陷后,代码如下。
(完整代码过于繁琐,下面只贴出缺陷部分代码修改后的结果)
FileInputStream fis = new FileInputStream(file);InputStreamReader isr = new InputStreamReader(fis, "UTF-8");BufferedReader br = new BufferedReader(isr);String line = "";StringBuffer sb = new StringBuffer();
小组代码分析
(此部分由本人和刘博谦(17070)完成)
1、FileWriter writer = new FileWriter("result.txt", true);
写文件流可能关闭异常,应该使用try/finally来确保写文件流会被成功关闭。
原有代码中使用了try/catch,但是并未使用finally语句,这就导致如果出现错误跳到catch,程序继续执行的话,写文件流一直会被占用,从而可能引发程序崩溃。
建议添加finally块来关闭写文件流。
2、FileWriter writer = new FileWriter("result.txt", true);
此行语句需要依赖默认编码来正常工作,为防止隐藏bug,应该指定一个编码,考虑到程序需求,指定UTF-8编码。
3、String line = new String("");
new String("")构造函数效率低,直接line=""即可。
4、message += (str.get(i) + " " + str.get(i + 1) + "\r\n");
循环中使用+来连接字符串,时间开销为二次方,建议修改使用StringBUffer.append(String)方法来提高效率。
参考资料
1、单词词频统计降序排序(代码贴)
2、阿里巴巴Java开发手册
转载于:https://www.cnblogs.com/jakejian/p/8735660.html
第4周小组作业:WordCount优化相关推荐
- HUST软测1504班第4周小组作业成绩:WordCount优化
说明 本次公布的成绩为第四周作业的结果: 第4周小组作业:WordCount优化 博客推荐:本次作业有一位同学完成有创意,推荐优秀博客.(优秀博客不会对成绩带来正面或者负面影响)PS:做任何创新的任务 ...
- HUST软测1504班第6周小组作业成绩
说明 本次公布的成绩为第6周小组作业的结果: 第6周小组作业:WordCount(详情见毕博平台) 如果同学对作业结果存在异议,可以: 在毕博平台讨论区的第6周作业第在线答疑区发帖申诉. 或直接在博客 ...
- 软件质量与测试--第二周作业 WordCount
软件质量与测试--第二周作业 WordCount Github地址: https://github.com/RicardoDZX/WordCount PSP: PSP2.1 PSP 阶段 预估耗时 ( ...
- 软件测试第4周小组作业:WordCount优化
小组github地址 https://github.com/whoNamedCody/wcPro 基本任务 一.PSP表格 PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分钟) Plan ...
- 第4周小组作业:WordCount优化版
小组github项目地址:https://github.com/Wegnery/New_WordCount 基础功能: 一.PSP表格 PSP2.1 PSP阶段 预估耗时 (分钟) 实际耗时 (分 ...
- 软件质量与测试第4周小组作业:WordCount优化
GitHub项目地址 https://github.com/Guchencc/WordCounter 组长: 陈佳文:负责词频统计模块与其他模块 组员: 屈佳烨:负责排序模块 苑子尚:负责输出模块 李 ...
- 第四周小组作业:WordCount优化
github项目地址:https://github.com/Wegnery/New_WordCount 一.基础功能部分:代码编写+单元测试 PSP表格 PSP2.1 PSP阶段 预估耗时(分钟) 实 ...
- 软件测试第四周作业WordCount优化
1.小组github地址:https://github.com/whoNamedCody 小组成员:17048冷福星 17050李慎纲 17039付佳韵 17040康之是 2.psp表格: P ...
- 第六周小组作业:软件测试与评估
一.基础任务部分:功能测试和测试管理 1.1计划说明 (1)对比测试产品为背单词APP:百词斩(基础产品)与扇贝单词(竞品). (2)测试进度表 测试进度表如下表所示(该表参照测试计划中的测试时间进度 ...
最新文章
- Python 中的 enumerate 函数
- 中文谐音怎么读_AOS中文社区创始人大豪:零隐链是AOS最恰当的中文表达
- HTML5 Canvas白板
- java五种加密技术理解
- 动态规划基础——爬楼梯(Leetcode 70)
- 用stack实现括号匹配
- 用 Python 创建你自己的加密货币(附源码)
- Win10连接上了wifi但是打开浏览器显示网络异常,诊断网络发现错误“远程计算机或者设备将不接受连接
- Python模拟简易版淘宝客服机器人
- 【同步与补偿】频率偏移
- [华为 HCNA ] VLAN的介绍和划分
- 弱爆了的鹊桥专用查询接口:taobao.tbk.dg.item.coupon.get( 好券清单API【导购】)接口
- Python爬取网易云音乐播放地址
- Axure 元件库-原型
- Greenplum【集群搭建 02】cgroup工具安装+用户资源组配置+集群资源组配置+数据库资源组配置+资源组相关信息(一篇学会资源组配置)
- 神舟电脑装linux双系统,神舟战神肿么装双系统
- Mysql安装-Centos7-阿里云虚拟主机
- 牛客网——华为题库(61~70)
- 献给程序员之如何与陌生人交谈
- 【Python】使用you-get下载bilibili视频合集