第一次个人编程作业
Github项目地址
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 30 | 30 |
Estimate | 估计这个任务需要多少时间 | 30 | 30 |
Development | 开发 | 1485 | 1805 |
Analysis | 需求分析 (包括学习新技术) | 800 | 1000 |
Design Spec | 生成设计文档 | 80 | 50 |
Design Review | 设计复审 | 20 | 15 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 15 | 15 |
Design | 具体设计 | 50 | 80 |
Coding | 具体编码 | 400 | 500 |
Code Review | 代码复审 | 20 | 25 |
Test | 测试(自我测试,修改代码,提交修改) | 100 | 150 |
Reporting | 报告 | 40 | 50 |
Test Repor | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 10 | 20 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 50 | 70 |
合计 | 1555 | 1885 |
设计与实现
解题思路
- 个人信息最终格式化成姓名,手机号,地址的格式
- 将姓名和手机号从字符串上提取出来
- 上网查找中国的行政划分,找出各级行政划分的关键词
- 这样就能划分出大部分地址,缺失的地址用空串表示
- 对于缺少省市关键词的,将地址和各省市比较(只比较每段信息的前两个字符)
程序设计
- 程序总共分成了三个类
- Main类,作为程序入口,调用AddressConvert类,读取和输出文件
- AddressConvert类,对字符串进行转换,提取其中的姓名和手机号,对地址进行分割,其中调用了AddressFill类补全缺少省市的地址
- AddressFill类,将地址信息和所有省市信息比对,找出相符的
- 地址分割使用正则表达式
- 地址的比先比较省再根据省比较市,提高查找效率
性能分析
刚开始对地址的比较,用到的数据是全都放在一起的,搜索市的时候会导致很多重复搜索,导致搜索的效率比较底下。经过改进,将代码改成了二级地址的匹配方式。
JProfiler生成的性能分析图如下:
单元测试
使用了JUnit对代码进行单元测试,主要是测试各个函数能否正常运行,设置了几组测试样例,测试程序对各种情况的处理。
测试数据主要有:
- 缺少省和市的
- 地级市和县级市同时存在的
- 还有其他地址关键词冲突的
测试代码如下:
import static org.junit.Assert.*;
import org.junit.Test;
public class UnitTest {
@Test
public void testAddrFill_1() {
String original="深圳";//市缺失,只比较前两个字
String changed="深圳市";
assertEquals(AddressJudge.addrFill(original), changed);
}
@Test
public void testAddrConvert_2() throws Exception {
//省市缺失
String original="1!张三,福建福州闽13599622362侯县上街镇福州大学10#111.";
String changed="{\"姓名\":\"张三\",\"手机\":\"13599622362\",
\"地址\":[\"福建省\",\"福州市\",\"闽侯县\",\"上街镇\",\"福州大学10#111\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
@Test
public void testAddrConvert_3() throws Exception {
//地级市和县级市同时存在
String original="1!风清扬,福建省福州市福13599622362清市上迳镇小东林.";
String changed="{\"姓名\":\"风清扬\",\"手机\":\"13599622362\",
\"地址\":[\"福建省\",\"福州市\",\"福清市\",\"上迳镇\",\"小东林\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
@Test
public void testAddrConvert_4() throws Exception {
//直辖市+单级地址缺失
String original="3!小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院.";
String changed="{\"姓名\":\"小美\",\"手机\":\"15822153326\",\"地址\":[\"北京\",\"
北京市\",\"东城区\",\"\",\"交道口东大街\",\"1号\",\"北京市东城区人民法院\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
@Test
public void testAddrConvert_5() throws Exception {
//省市缺失
String original="1!张三,福建福州闽13599622362侯县上街镇福州大学10#111.";
String changed="{\"姓名\":\"张三\",\"手机\":\"13599622362\",
\"地址\":[\"福建省\",\"福州市\",\"闽侯县\",\"上街镇\",\"福州大学10#111\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
@Test
public void testAddrConvert_6() throws Exception {
//地级市和县级市同时存在
String original="1!风清扬,福建省福州市福13599622362清市上迳镇小东林.";
String changed="{\"姓名\":\"风清扬\",\"手机\":\"13599622362\",
\"地址\":[\"福建省\",\"福州市\",\"福清市\",\"上迳镇\",\"小东林\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
@Test
public void testAddrConvert_7() throws Exception {
//自治区和区同时存在
String original="1!令狐冲,内蒙古自治区呼和13599622362浩特市新城区内蒙古工业大学.";
String changed="{\"姓名\":\"令狐冲\",\"手机\":\"13599622362\",
\"地址\":[\"内蒙古自治区\",\"呼和浩特市\",\"新城区\",\"\",\"内蒙古工业大学\"]}";
assertEquals(AddressBasic.addrConvert(original), changed);
}
}
单元测试覆盖率:
异常处理
异常处理主要是设置在文件读写部分的,
代码如下:
try {
fis = new FileInputStream("d:/1.txt");
isr = new InputStreamReader(fis, "UTF-8");
br = new BufferedReader(isr);
fos = new FileOutputStream("d:/2.txt");
osw = new OutputStreamWriter(fos, "UTF-8");
bw = new BufferedWriter(osw);
String line=br.readLine();
bw.write("["+AddressBasic.addrConvert(line));
while ((line = br.readLine()) != null)
{
bw.write(",");
bw.newLine();
bw.write(AddressBasic.addrConvert(line));
}
bw.write("]");
} catch (Exception ex) {
ex.printStackTrace();
}