1.Github项目地址
2.PSP表格
Planning | 计划 | 30 | 20 |
Estimate | 估计这个任务需要多少时间 | 20 | 20 |
Development | 开发 | 480 | 420 |
Analysis | 需求分析 (包括学习新技术) | 240 | 240 |
Design Spec | 生成设计文档 | 30 | 20 |
Design Review | 设计复审 | 20 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
Design | 具体设计 | 30 | 40 |
Coding | 具体编码 | 480 | 520 |
Code Review | 代码复审 | 30 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 120 | 60 |
Reporting | 报告 | 30 | 20 |
Test Report | 测试报告 | 30 | 30 |
Size Measurement | 计算工作量 | 20 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 40 | 60 |
| 合计 | 1620 | 1530 |
3.设计实现过程
- 本题是输入字符串匹配、分割处理的题目,通过分析题面,正则表达式一定是解题的关键。数据需要处理成json格式。所以做题前的准备就是要去学习正则表达式和json的相关知识。
- 本题中电话号码是一个随机插入且不与其他数字相连的字符串,会扰乱匹配,所以首先提取,put进入json对象。
- 电话号码提取后,姓名后面一定是‘,’字符,特征明显,通过正则表达式轻易提取,put进入json对象。
- 提取电话和姓名后,剩下的字符串是纯粹的地址,根据题目有5级地址和7级地址之分,首先处理5级地址。通过查找地址文档,正则表达式切出省、市简称,再依次匹配分割,得到字符串数组,put进入json对象。
- 在5级地址的基础上处理7级地址,将5级地址的最后一个字符串单独处理,分成路级、号级、其他,其他,通过正则表达式处理。
- 一条地址信息处理完毕后,add进jsonArray。
- 代码最后设计了一个类,共有7个函数:提取电话findtel(),提取名字findname(),提取5级地址findaddr5(),提取7级地址findaddr7(),返回字符串printJson(),打印到文件put()。这七个函数相对独立,只有在findaddr7()中调用了findaddr5()。
- 关键函数findaddr5()流程图:
4.改进及性能分析
- 零零散散在改进程序性能上花了180分钟吧,因为顺便把算法也改进了,我的第一份代码所用的表示同一份,数据很多,但是其实省份根本不需要,我就把省份的匹配表单独列出,大大减少了查表时间。
- 性能分析图:
- 消耗最大的函数:
public static String[] findaddr5(String line)
{
String[] addr = {"","","","",line};
String[] province = {""};
String FileName="\\shengfen.txt";
File myFile=new File(FileName);
if(!myFile.exists())
{
System.err.println("Can't Find " + "省份");
}
try
{
BufferedReader in = new BufferedReader(new FileReader(myFile));
province = in.readLine().split(",");
in.close();
}
catch (IOException e)
{
e.getStackTrace();
}
String pattern1 = "(.*)(维吾尔族自治区|壮族自治区|回族自治区|自治区|省|特别行政区|市)";
String pattern11 = "(.*自治区|.*省|.*特别行政区)(.*)";
boolean flag = true;
for(String a:province)//提取省份
{
Pattern r1 = Pattern.compile(pattern1);
Matcher m1 = r1.matcher(a);
String comp = " ";
if(m1.find())
comp = m1.group(1);//提取所有省份的简称
Pattern r2 = Pattern.compile("(" + comp + ")(.*)");
Matcher m2 = r2.matcher(line);
if(m2.find())//比对省份
{
if(m2.group(1).equals("北京")||m2.group(1).equals("天津")//直辖市特殊处理
||m2.group(1).equals("上海")||m2.group(1).equals("重庆"))
{
flag = false;
addr[0] = comp;
addr[1] = a;
if(line.substring(0,3).equals(comp + "市"))//删除line中的“市”
{
line = line.substring(3);
}
else
{
line = line.substring(2);
}
addr[4] = line;
}
else//删除后缀
{
addr[0] = a;
Pattern r = Pattern.compile(pattern11);
Matcher m = r.matcher(line);
if(m.find())
{
line = m.group(2);
}
else
{
line = m2.group(2);
}
addr[4] = line;
}
break;
}
}
//找市
String pattern2 = "(.*自治州|.*市|.*地区|.*盟)(.*)";
String pattern22 = "(.*)(自治州|市|地区|盟)(.*)";
FileName="\\shi.txt";
myFile=new File(FileName);
if(!myFile.exists())
{
System.err.println("Can't Find " + "市");
}
try
{
if(flag)
{
BufferedReader in = new BufferedReader(new FileReader(myFile));
String shifullname = " ";
while((shifullname = in.readLine()) != null)
{
Pattern r = Pattern.compile("(.{7})([^\\x00-\\xff]{2,10})(.*)");
Matcher m = r.matcher(shifullname);
if(m.find())
shifullname = m.group(2);
Pattern r1 = Pattern.compile(pattern22);
Matcher m1 = r1.matcher(shifullname);
String shisimplename = " ";
if(m1.find())
{
if(!m1.group(3).equals(""))
{
continue;
}
shisimplename = m1.group(1);//得到所有市级的简称
Pattern r2 = Pattern.compile("(" + shisimplename + ")(.*)");
Matcher m2 = r2.matcher(line);
if(m2.find())//比对市级地址
{
addr[1] = shifullname;
Pattern r3 = Pattern.compile(pattern2);//切除后缀
Matcher m3 = r3.matcher(line);
if(m3.find())
{
line = m3.group(2);
}
else
{
line = m2.group(2);
}
addr[4] = line;
break;
}
}
}
in.close();
}
String pattern3 = "(.{2,7}区|.*市辖区|.*市|.*县|.*自治县|.*旗|.*自治旗|.*林区|.*特区)(.*)";
Pattern r = Pattern.compile(pattern3);
Matcher m = r.matcher(line);
if(m.find())
{
addr[2] = m.group(1);
line = m.group(2);
addr[4] = line;
}
String pattern4 = "(.*街道|.*镇|.*乡|.*民族乡|.*苏木|.*民族苏木|.*县辖区)(.*)";
r = Pattern.compile(pattern4);
m = r.matcher(line);
if(m.find())
{
addr[3] = m.group(1);
line = m.group(2);
addr[4] = line;
}
}
catch (IOException e)
{
e.getStackTrace();
}
return addr;
}
5.计算模块部分单元测试展示
public void testFindaddr7() {
Hellojava.findaddr7("小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院");
Hellojava.findaddr7("福建省福州市鼓楼区鼓西街道湖滨路110号湖滨大厦一层");
Hellojava.findaddr7("小林,青海省海西蒙古13616071246族藏族自治州格尔木市");
Hellojava.findaddr7("王五,福建省福州市鼓楼18960221533区五一北路123号福州鼓楼医院");
Hellojava.findaddr7("小赵,新疆维吾尔自治区和田地区于田13599622362县昆仑路12");
Hellojava.findaddr7("李四,福建福州13756899511市鼓楼区鼓西街道湖滨路110号湖滨大厦一层");
Hellojava.findaddr7("小赵,新疆和田地区于田13599622362县昆仑路12");
Hellojava.findaddr7("张三,福建福州闽13599622362侯县上街镇福州大学10#111");
Hellojava.findaddr7("张三,福建福州13599622362上街镇福州大学10#111");
Hellojava.findaddr7("小李,广西西青区静13599622362水道1号");
}
- 处理了testFindaddr7()、testFindname()、testFindtel()、testFindname()函数
- 单元测试的设计
- 1级:普通省份全地址,直辖市全地址,自治区全地址,普通省份市缺失地址,自治区市缺失地址,普通省份后缀缺失地址,自治区后缀缺失地址,市县级缺失地址,省市后缀缺失地址,直辖市后缀缺失地址。
- 2级:在1级难度下随机缺失街道、门牌号级地址。
6.计算模块部分异常处理说明
- 文件打开失败抛出异常IOException e,数据输入不符合格式抛出IOException e
- 示例:
try
{
BufferedReader in = new BufferedReader(new FileReader(myFile));
province = in.readLine().split(",");
in.close();
}
catch (IOException e)
{
e.getStackTrace();
} - 覆盖率
7.PSP
Planning | 计划 | 20 |
Estimate | 估计这个任务需要多少时间 | 20 |
Development | 开发 | 420 |
Analysis | 需求分析 (包括学习新技术) | 240 |
Design Spec | 生成设计文档 | 20 |
Design Review | 设计复审 | 10 |
Coding Standard | 代码规范 (为目前的开发制定合适的规范) | 20 |
Design | 具体设计 | 40 |
Coding | 具体编码 | 520 |
Code Review | 代码复审 | 20 |
Test | 测试(自我测试,修改代码,提交修改) | 60 |
Reporting | 报告 | 20 |
Test Report | 测试报告 | 30 |
Size Measurement | 计算工作量 | 30 |
Postmortem & Process Improvement Plan | 事后总结, 并提出过程改进计划 | 60 |
| 合计 | 1530 |