Part 1.Github
Destr
Part 2.PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 40 | 40 |
· Estimate | · 估计这个任务需要多少时间 | 40 | 40 |
Development | 开发 | 1060 | 1360 |
· Analysis | · 需求分析 (包括学习新技术) | 300 | 420 |
· Design Spec | · 生成设计文档 | 25 | 20 |
· Design Review | · 设计复审 | 15 | 20 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 20 | 10 |
· Design | · 具体设计 | 90 | 120 |
· Coding | · 具体编码 | 480 | 600 |
· Code Review | · 代码复审 | 30 | 50 |
· Test | · 测试(自我测试,修改代码,提交修改) | 100 | 120 |
Reporting | 报告 | 100 | 130 |
· Test Repor | · 测试报告 | 40 | 60 |
· Size Measurement | · 计算工作量 | 20 | 10 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 40 | 60 |
· 合计 | 1200 | 1530 |
Part 3.设计与实现
设计
看到题目后首先是确定了给出的地址的几个特征信息:
-
手机号不会与其他数字放在一起
-
姓名后又逗号分隔
-
地址信息由大到小从左到右依次排列
于是就大致确定了自己的实现思路:
- 使用正则表达式匹配手机号并提取出来
- 以逗号为分隔符提取出难度等级和姓名
- 使用正则表达式根据提前查找的省市的名称进行匹配
- 依次从左到右根据“县/区/市”,“镇/乡/街道”等关键字依次查找各等级信息,查不到则为空
ps:其中要特别判断三个直辖市,它们的一二级地址信息仅差有没有“市”这个字
(看到其他人有使用API接口或者爬取全国地址分类的Json
包然后直接进行匹配,这个也有想过,不过由于也是刚刚开始入手Java,很多东西也不是很懂,于是只能老老实实使用这种一级一级判断的方式来提取地址,同时难度为3!的情况也没有进行实现,代码也没有什么特别独到之处 菜是原罪)
流程图如下(略显粗糙)
实现
暂时还没有学过Java中多个类的使用方式,所以就将代码全都放到了一个类Main
中,在类中有多个方法,分别实现不同的功能
以下就是代码中所有实现功能的方法,分别是文件读写和提取各级地址
![](https://img2018.cnblogs.com/blog/1330790/201909/1330790-20190927190510200-1512301952.png)
下面则是很长的主函数代码,主函数的主要功能是调用各个方法对地址数据进行处理(一开始写的时候也没有注意,所以写着写着就把一些乱七八糟的处理都写到了主函数中,后来也没有改主要是懒,就这样放到主函数中了)
public static void main(String[] args) throws IOException{
Main ans =new Main();//用于保存答案
String ss=ans.readFile();
String[] address=ss.split("
");
JsonArray ansarr=new JsonArray();
for(String loop:address){
ans.init();
ans.s=loop;
Pattern pattern=Pattern.compile("\d{11}");
Matcher matcher=pattern.matcher(ans.s);
if(matcher.find())
{
ans.setPhoneNumber(matcher.group());
}//寻找手机号并提取出来
//System.out.println(ans.phoneNumber);
String[] s1=ans.s.split("\d{11}");
ans.s=s1[0]+s1[1];
String[] s2=ans.s.split(",");
char level=s1[0].charAt(0);//获取难度等级
//System.out.println(level);
String _name="";
for(int i=2;i<s2[0].length();i++){
_name+=s2[0].charAt(i);
}//提取姓名
ans.setName(_name);
ans.s=s2[1];
JsonObject object=new JsonObject();
object.addProperty("姓名",ans.name);
object.addProperty("手机",ans.phoneNumber);
JsonArray array=new JsonArray();
if(level=='1')
{
ans=ans.getFirstAddress(ans);
ans=ans.getSecondAddress(ans);
ans=ans.getThirdAddress(ans);
ans=ans.getForthAddress(ans);
for(int i=0;i<ans.s.length();i++)
{
if(ans.s.charAt(i)=='.')break;
ans.address[5]+=ans.s.charAt(i);
}
for(int i=1;i<=5;i++)
{
array.add(ans.address[i]);
}
}//1!难度 提取五级地址
if(level=='2')
{
ans=ans.getFirstAddress(ans);
ans=ans.getSecondAddress(ans);
ans=ans.getThirdAddress(ans);
ans=ans.getForthAddress(ans);
ans=ans.getFifthAddress(ans);
ans=ans.getSixthAddress(ans);
for(int i=0;i<ans.s.length();i++)
{
if(ans.s.charAt(i)=='.')break;
ans.address[7]+=ans.s.charAt(i);
}
for(int i=1;i<=7;i++)
{
array.add(ans.address[i]);
}
}//二级难度 提取七级地址
object.add("地址",array);
ansarr.add(object);
}
ans.writeFile(ansarr);
}
Part 4.接口性能改进
性能改进的话主要还是在整体代码写完之后在一些数据处理上做了些简单优化,比如提前跳出循环等,大约花费了30分钟左右,性能分析图如下
![](https://img2018.cnblogs.com/blog/1330790/201909/1330790-20190927190328924-1541642077.png)
![](https://img2018.cnblogs.com/blog/1330790/201909/1330790-20190927190353360-445682069.png)
程序中消耗最大的函数:
- 读取数据函数,该函数中包含了读取过程中对字符的处理,空间及时间消耗都较大
Part 5.单元测试展示
单元测试代码:
public Main getFirstAddress(Main res){
String first="";
Pattern pattern1=Pattern.compile(myFirstAddress);
Matcher matcher1=pattern1.matcher(res.s);
if(matcher1.find()){
first=matcher1.group();
if(first.equals("上海")||first.equals("北京")||first.equals("天津"))
{
if(res.s.charAt(2)=='市')
{
res.s=res.s.substring(3,res.s.length()-1);
}
else{
res.s=res.s.substring(2,res.s.length()-1);
}
}
else if(first.equals("黑龙江"))
{
if(res.s.charAt(3)=='省')
{
first+=res.s.charAt(3);
res.s=res.s.substring(4,res.s.length()-1);
}
else
{
first+='省';
res.s=res.s.substring(3,res.s.length()-1);
}
}
else
{
if(res.s.charAt(2)=='省'){
first+='省';
res.s=res.s.substring(3,res.s.length()-1);
}
else
{
first+='省';
res.s=res.s.substring(2,res.s.length()-1);
}
}
}
Pattern pattern2=Pattern.compile("自治区");
Matcher matcher2=pattern2.matcher(res.s);
if(matcher2.find()){
int index=res.s.indexOf("区");
first=res.s.substring(0,index);
res.s=res.s.substring(index+1,res.s.length()-1);
}
res.address[1]=first;
return res;
}//提取一级地址
public Main getSecondAddress(Main res){
if(res.address[1].equals("上海")||res.address[1].equals("北京")||res.address[1].equals("天津"))
{
res.address[2]=res.address[1]+'市';
return res;
}
String second="";
Pattern pattern =Pattern.compile(mysecondAdress);
Matcher matcher=pattern.matcher(res.s);
if(matcher.find()){
second=matcher.group();
res.s=res.s.substring(second.length(),res.s.length());
second +='市';
if(res.s.charAt(0)=='市'){
res.s=res.s.substring(1,res.s.length());
}
}
res.address[2]=second;
return res;}//提取二级地址
代码主要功能:
这一段代码主要用于提取一级地址和二级地址
构造测试数据思路:
主要是构造各种情况的地址,尽量涉及所有需要处理的情况
单元测试截图:
测试覆盖率截图:
Part 6.异常处理说明
当路号丢失而七级地址含有“号”时
样例:
2!李立,福建福州闽侯县上街镇13524568956福州大学56号楼111(缺失"学院路2号")
写在最后
由于刚刚开始Java的学习,所以这次的软工作业也是边学边做,学习文件读写、正则表达式、还有其他Java里面其他一些很好用的函数,还有就是第一次接触Json数组,也是研究了半天才看懂并会学着使用,总之边做作业边学习感觉上还是蛮好的,可以根据作业中的需求学习,也省得自己不知道该从何处下手。接着又要开始十三水的作业了,真难顶