一、仓库地址
二、PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 45 | 60 |
· Estimate | · 估计这个任务需要多少时间 | 45 | 60 |
Development | 开发 | 1850 | 2205 |
· Analysis | · 需求分析 (包括学习新技术) | 270 | 360 |
· Design Spec | · 生成设计文档 | 60 | 90 |
· Design Review | · 设计复审 | 30 | 45 |
· Coding Standard | · 代码规范 (为目前的开发制定或选择合适的规范) | 20 | 30 |
· Design | · 具体设计 | 300 | 330 |
· Coding | · 具体编码 | 780 | 840 |
· Code Review | · 代码复审 | 90 | 150 |
· Test | · 测试(自我测试,修改代码,提交修改) | 300 | 360 |
Reporting | 报告 | 110 | 125 |
· Test Report | · 测试报告 | 60 | 60 |
· Size Measurement | · 计算工作量 | 30 | 35 |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出改进计划 | 20 | 30 |
· 合计 | 2005 | 2390 |
三、计算模块接口的设计与实现过程
(1)解题思路
思考和找资料过程:
刚打开作业的时候,天花乱坠的要求直接把我整懵了,头晕,再打开,还是头晕。逃避了一会,想着早点看懂题目能够早点开始,决定看个大概之后,从代码着手:
1.题目中的数据是姓名、手机号和地址这三个字符串和一些标点符号的组合,而题目要求我们将其分开,同时去掉一些标点,我想着是否有一些方法能够去把这些字符串分开,向大佬寻求帮助后得知可以使用Java的正则表达式,于是去慕课和一些博客中学习了相关知识。
2.之后想着如果通过正则表达式能够将姓名、手机号和地址分开的话,应该也能够再利用它来对地址进行详细的划分,果不其然,正则表达式真是个好东西(激动地搓搓手。
3.接着就是仔细分析代码需求了,在这上面真是走了不少弯路。大致了解了三个level的要求,首先level1是要求对地址进行五级划分,而level2和level3则是七级划分,level1和level2都会出现“省”和“市”这两个字符会缺失的情况,而level3和它们根本不是一个level,它会出现缺失,甚至需要补全,了解到需要导入地图,ok fine,我先放弃这个,能把level1和level2打出来,再尝试一下去解决补全的问题,对于不同级别的不同情况,我打开了淘宝,选择设置收货地址,随手点一点找了一下不同的情况。
再之后考虑的就是github和其他要求里面需要下载的软件的使用了,也是跟着几篇博客里面的教程一步一步做下来。同时感觉很幸运有认识的好友是学计算机的,我从他们那里获得了不少帮助,也很感谢班上认真解答我的疑问的同学。
解题步骤
Step 1. 利用正则表达式将前缀x!,姓名,手机号和地址分开
Step 2. 通过分离出来的前缀x判断进行什么级别的地址划分
Step 3. 利用正则表达式判断是否为直辖市并且分割剩余的详细地址
(2)设计实现过程
我利用Java来写这个程序。由于都是字符串切割这一类问题,我只用了一个类。类中有一个main方法和其他几种工具方法和输出方法,在main方法中先对字符串进行切割,把前缀x,姓名,手机号和地址分开后,先调用getProvince方法判断是否有省级或者市级的级别后缀缺失,再根据前缀x的不同,调用了不同的方法进行地址的详细划分,最后通过输出函数输出。以下是几个方法:
方法
方法名 | 说明 |
---|---|
Map<String, Object> getJson(ArrayList |
输出函数 |
ArrayList |
工具函数:用于进行Level1的详细地址划分 |
ArrayList |
工具函数:用于进行Level2和Level3的详细地址划分 |
ArrayList |
工具函数:用于解决缺少省、市等字符串的情况 |
算法关键及独到之处
算法关键
1、将前缀x!,姓名,手机号和地址的分开处理,同时删除最后的英文句号“.”。
step1.通过“,”将字符串切割成x!+姓名和手机号+地址两部分
String level_name = str.split(",")[0];
String level = level_name.split("[!]")[0];
step2.通过“!”分割前缀x和姓名
String name = level_name.split("[!]")[1];
String phone_address = str.split(",")[1];
step3.通过创建匹配器的方式分割手机号和地址
Pattern pattern = Pattern.compile("((13[0-9])|(14[5|7])|(15([0-3]|[5-9]))|(18[0,5-9]))\d{8}");
//创建匹配给定输入与此模式的匹配器。
Matcher matcher = pattern.matcher(phone_address);
while(matcher.find()) {
sb2.append(matcher.group()); }
String phone = sb2.toString();
String address = phone_address.replaceAll(phone, "");
step4.用replaceAll删除“.”
address = address.replaceAll("[.]","");
2、用getProvince方法处理省级或者市级的级别后缀缺失的情况。
我的方法很简单,总而言之就是用了if---else语句:
判断判断是否有“省” :if(!address.matches(".*省.*")){}
,
有则进入之后的利用前缀x判断进行什么级别的地址划分,
没有则接着判断是否有“市”:if(address.matches(".*市.*")) {}
,
没有则接着判断第三级地址else if(address.matches(".*(区|县).*")){}
,
将缺失的级别后缀补全,结束后返回xx省xx市+后面的详细地址。
3、根据前缀x判断进行五级地址分割还是七级地址分割,通过getMatchesAddress方法进行五级地址分割,通过getMatchesAddressSeven进行七级地址分割。
五级和七级的分割道理其实是差不多的,就是利用正则表达式逐级分割,我的方法还是很简单,简单来说就是把每一级的不同情况列举出来,所以碰到比较不规则的地址的时候可能会出错。我就拿七级地址分割来说,找出每一级地址的不同情况,比较不一样的是省级,还需要判断是否是直辖市。
- 省级:
if(address.matches(".*(省|自治区|行政区).*")) {
int index = address.indexOf("省");
int index2 = address.indexOf("自治区");
int index3 = address.indexOf("行政区");
if(index > -1) {
pr = address.substring(0,index+1);
temp = temp.substring(index+1);
}
if(index2 > -1) {
pr = address.substring(0,index2+3);
temp = temp.substring(index2+3);
}
if(index3 > -1)
{
pr = address.substring(0,index3+3);
temp = temp.substring(index3+3);
}
if(pr.matches(".*北京.*")) {
pr = "北京";
temp = address.substring(index+1);
}
if(pr.matches(".*上海.*")) {
pr = "上海";
temp = address.substring(index+1);
}
if(pr.matches(".*天津.*")) {
pr = "天津";
temp = address.substring(index+1);
}
if(pr.matches(".*重庆.*")) {
pr = "重庆";
temp = address.substring(index+1);
}
}
- 市级:
if(temp.matches(".*市.*")) {
int index = temp.indexOf("市");
if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
{
city = temp.substring(0,index+1);
}
else{
city = temp.substring(0,index+1).replace(pr,"").trim();
}
temp = temp.substring(index+1);
}
剩余的五个级别同理:
- 第三级:
if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {}
- 第四级:
if(temp.matches(".*(街道|镇|乡).*")) {}
- 第五级:
if(temp.matches(".*(路|巷|道|街|弄|胡同).*")) {}
- 第六级:
if(temp.matches(".*号.*")) {}
- 第七级:
else {village = temp;}
4、最后用getJson方法输出。
独到之处
嗯,我的方法真的很简单,毕竟只是个速成品,把地址单独分割出来后,利用正则表达式分割详细地址,在每一级中不停地判断和列举,并没有什么特别的地方。但是能解决一定问题的方法就是好方法嘛,对于我来说能有输出已经是一件很快乐的事情了。非要厚脸皮地说有什么独到之处的话,简单粗暴算嘛,勉强算吧,嘻嘻。(给点面子
四、计算模块接口部分的性能改进
(1)改进时间
这个真的花了蛮多时间的,至少三个小时,甚至更多,首先是因为没有看清楚代码需求,不知道要分级,也不知道不同级别对应不同的情况,还有就是没有考虑到不同级别的不同情况,一开始只考虑省市区县这样简单的几种情况,后来发现还有其他比较少见的一些情况,比如自治区、特别行政区之类的。
(2)改进思路
- 分级:把前缀分割出来后,利用前缀进行划分,同时设置两种方法,分别用于五级地址分割和七级地址分割。
- 不同级别的不同情况:在我能想到和找到的情况范围内,在每个级别进行判断和列举。
(3)性能分析图
我使用的是Jprofiler进行性能分析
消耗最大的方法是getMatchesAddress:
public static ArrayList<String> getMatchesAddress (String address) {
String pr = "";
String city = "";
String county = "";
String town = "";
String village = "";
String temp = address;
if(address.matches(".*(省|自治区|行政区).*")) {
int index = address.indexOf("省");
int index2 = address.indexOf("自治区");
int index3 = address.indexOf("行政区");
if(index > -1) {
pr = address.substring(0,index+1);
temp = temp.substring(index+1);
}
if(index2 > -1) {
pr = address.substring(0,index2+3);
temp = temp.substring(index2+3);
}
if(index3 > -1)
{
pr = address.substring(0,index3+3);
temp = temp.substring(index3+3);
}
if(pr.matches(".*北京.*")) {
pr = "北京";
temp = address.substring(index+1);
}
if(pr.matches(".*上海.*")) {
pr = "上海";
temp = address.substring(index+1);
}
if(pr.matches(".*天津.*")) {
pr = "天津";
temp = address.substring(index+1);
}
if(pr.matches(".*重庆.*")) {
pr = "重庆";
temp = address.substring(index+1);
}
}
if(temp.matches(".*市.*")) {
int index = temp.indexOf("市");
if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
{
city = temp.substring(0,index+1);
}
else{
city = temp.substring(0,index+1).replace(pr,"").trim();
}
temp = temp.substring(index+1);
}
if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {
int index = temp.indexOf("区");
int index2 = temp.indexOf("县");
int index3 = temp.indexOf("市");
int index4 = temp.indexOf("海域");
int index5 = temp.indexOf("岛");
int index6 = temp.indexOf("旗");
if(index > -1) {
county = temp.substring(0,index+1).replace(city, "").trim();
temp = temp.substring(index+1);
}
if(index2 > -1) {
county = temp.substring(0,index2+1).replace(city, "").trim();
temp = temp.substring(index2+1);
}
if(index3 > -1) {
county = temp.substring(0,index3+1).replace(city, "").trim();
temp = temp.substring(index3+1);
}
if(index4 > -1) {
county = temp.substring(0,index4+2).replace(city, "").trim();
temp = temp.substring(index4+2);
}
if(index5 > -1) {
county = temp.substring(0,index5+1).replace(city, "").trim();
temp = temp.substring(index5+1);
}
if(index6 > -1) {
county = temp.substring(0,index6+1).replace(city, "").trim();
temp = temp.substring(index6+1);
}
}
if(temp.matches(".*(街道|镇|乡).*")) {
int index = temp.indexOf("街道");
int index2 = temp.indexOf("镇");
int index3 = temp.indexOf("乡");
if(index > -1) {
town = temp.substring(0,index+1).replace(county, "").trim();
village = temp.substring(index+1);
}
if(index2 > -1) {
town = temp.substring(0,index2+1).replace(county, "").trim();;
village = temp.substring(index2+1);
}
if(index3 > -1) {
town = temp.substring(0,index3+1).replace(county, "").trim();
village = temp.substring(index3+1);
}
}else {
village = temp;
}
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add(pr);
arrayList.add(city);
arrayList.add(county);
arrayList.add(town);
arrayList.add(village);
return arrayList;
}
五、计算模块部分单元测试展示
(1)单元测试代码
public class test2 {
public static void main(String[] args) {
String[] arr = {"山西省太原市小店区鼓西街道湖滨路119号湖滨大厦一层",
"广西壮族自治区南宁市江南区白沙大道20号",
"新疆维吾尔自治区乌鲁木齐市乌鲁木齐县万盛大街4706号",
"湖南省长沙市天心区芙蓉中路二段116-1众东国际104室",
"福建省厦门市集美区理工南路852号厦门工艺美术学院4#205",
"四川省成都市武侯区人民南路四段20号叶婆婆钵钵鸡",
"福建省泉州市丰泽区丰泽街道丰迎路15号",
"福建省泉州市鲤城区庄府巷107号",
"湖南省长沙市天心区裕南街85号盟重烧烤",
"云南省水富县云川路1号水富火车站货运大楼",
for (int a = 0; a < arr.length; a++) {
Object[] array = getProvince(arr[a]).toArray();
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);}
System.out.println("---------------------------------------------");}}
public static ArrayList<String> getMatchesAddressSeven (String address) {
String pr = "";
String city = "";
String county = "";
String town = "";
String path = "";
String mark = "";
String village = "";
String temp = address;
if(address.matches(".*(省|自治区|行政区).*")) {
int index = address.indexOf("省");
int index2 = address.indexOf("自治区");
int index3 = address.indexOf("行政区");
if(index > -1) {
pr = address.substring(0,index+1);
temp = temp.substring(index+1);
}
if(index2 > -1) {
pr = address.substring(0,index2+3);
temp = temp.substring(index2+3);
}
if(index3 > -1)
{
pr = address.substring(0,index3+3);
temp = temp.substring(index3+3);
}
if(pr.matches(".*北京.*")) {
pr = "北京";
temp = address.substring(index+1);
}
if(pr.matches(".*上海.*")) {
pr = "上海";
temp = address.substring(index+1);
}
if(pr.matches(".*天津.*")) {
pr = "天津";
temp = address.substring(index+1);
}
if(pr.matches(".*重庆.*")) {
pr = "重庆";
temp = address.substring(index+1);
}
}
if(temp.matches(".*市.*")) {
int index = temp.indexOf("市");
if(temp.matches(".*北京.*|.*上海.*|.*天津.*|.*重庆.*"))
{
city = temp.substring(0,index+1);
}
else{
city = temp.substring(0,index+1).replace(pr,"").trim();
}
temp = temp.substring(index+1);
}
if(temp.matches(".*(区|县|市|海域|岛|旗).*")) {
int index = temp.indexOf("区");
int index2 = temp.indexOf("县");
int index3 = temp.indexOf("市");
int index4 = temp.indexOf("海域");
int index5 = temp.indexOf("岛");
int index6 = temp.indexOf("旗岛");
if(index > -1) {
county = temp.substring(0,index+1).replace(city, "").trim();
temp = temp.substring(index+1);
}
if(index2 > -1) {
county = temp.substring(0,index2+1).replace(city, "").trim();
temp = temp.substring(index2+1);
}
if(index3 > -1) {
county = temp.substring(0,index3+1).replace(city, "").trim();
temp = temp.substring(index3+1);
}
if(index4 > -1) {
county = temp.substring(0,index4+2).replace(city, "").trim();
temp = temp.substring(index4+2);
}
if(index5 > -1) {
county = temp.substring(0,index5+1).replace(city, "").trim();
temp = temp.substring(index5+1);
}
if(index6 > -1) {
county = temp.substring(0,index6+1).replace(city, "").trim();
temp = temp.substring(index6+1);
}
}
if(temp.matches(".*(街道|镇|乡).*")) {
int index = temp.indexOf("街道");
int index2 = temp.indexOf("镇");
int index3 = temp.indexOf("乡");
if(index > -1) {
town = temp.substring(0,index+2).replace(county, "").trim();
temp = temp.substring(index+2);
}
if(index2 > -1) {
town = temp.substring(0,index2+1).replace(county, "").trim();;
temp = temp.substring(index2+1);
}
if(index3 > -1) {
town = temp.substring(0,index3+1).replace(county, "").trim();
temp = temp.substring(index3+1);
}
}
if(temp.matches(".*(路|巷|道|街|弄|胡同).*")) {
int index = temp.indexOf("路");
int index2 = temp.indexOf("巷");
int index3 = temp.indexOf("道");
int index4 = temp.indexOf("街");
int index5 = temp.indexOf("弄");
int index6 = temp.indexOf("胡同");
if(index > -1) {
path = temp.substring(0,index+1).replace(town, "").trim();
temp = temp.substring(index+1);}
if(index2 > -1) {
path = temp.substring(0,index2+1).replace(town, "").trim();
temp = temp.substring(index2+1);}
if(index3 > -1) {
path = temp.substring(0,index3+1).replace(town, "").trim();
temp = temp.substring(index3+1);}
if(index4 > -1) {
path = temp.substring(0,index4+1).replace(town, "").trim();
temp = temp.substring(index4+1);}
if(index5 > -1) {
path = temp.substring(0,index5+1).replace(town, "").trim();
temp = temp.substring(index5+1);}
if(index6 > -1) {
path = temp.substring(0,index6+2).replace(town, "").trim();
temp = temp.substring(index6+2);}
}
if(temp.matches(".*号.*")) {
int index = temp.indexOf("号");
mark = temp.substring(0,index+1).replace(path, "").trim();
village = temp.substring(index+1);
}
else {
village = temp;
}
ArrayList<String> arrayList = new ArrayList<String>();
arrayList.add(pr);
arrayList.add(city);
arrayList.add(county);
arrayList.add(town);
arrayList.add(path);
arrayList.add(mark);
arrayList.add(village);
return arrayList;
}
测试答案为:
山西省
太原市
小店区
鼓西街道
湖滨路
119号
湖滨大厦一层
---------------------------------------------
广西壮族自治区
南宁市
江南区
白沙大道
20号
---------------------------------------------
新疆维吾尔自治区
乌鲁木齐市
乌鲁木齐县
万盛大街
4706号
---------------------------------------------
湖南省
长沙市
天心区
芙蓉中路
二段116-1众东国际104室
---------------------------------------------
福建省
厦门市
集美区
理工南路
852号
厦门工艺美术学院4#205
---------------------------------------------
四川省
成都市
武侯区
人民南路
四段20号
叶婆婆钵钵鸡
---------------------------------------------
福建省
泉州市
丰泽区
丰泽街道
丰迎路
15号
---------------------------------------------
福建省
泉州市
鲤城区
庄府巷
107号
---------------------------------------------
湖南省
长沙市
天心区
裕南街
85号
盟重烧烤
---------------------------------------------
云南省
水富县
云川路
1号
水富火车站货运大楼
---------------------------------------------
(2)测试的函数
测试的函数是getMatchesAddressSeven,已经在(1)中展示
(3)构造测试数据的思路
构造测试数据来源主要有三种:
1、选择了一些比较奇怪的名字,比如自治区、巷、街之类的。
2、从百度地图上随手点了一个位置。
3、选择了一些我去过的地方。
(4)测试覆盖率图
主方法的覆盖率:
测试方法的覆盖率:
六、计算模块部分异常处理说明
(1)在输入的省级是xxx自治区xx市,且省级和市级后缀都缺失的情况下,会出现补全错误和信息缺失的现象。
输入:2!小王,广西壮族15822153326南宁江南区白沙大道20号.
输出:{"姓名":"小王","手机":"15822153326","地址":["广西省","族市","宁江南区","","白沙大道","20号",""]}
(2)针对上面那种情况我想试试看如果把市级后缀加上是否会出现缺失,虽然不出现缺失了,但是把省市混淆在一起了。
输入:2!小王,广西壮族15822153326南宁市江南区白沙大道20号.
输出:{"姓名":"小王","手机":"15822153326","地址":["广西壮族南宁省","广西壮族南宁市","江南区","","白沙大道","20号",""]}
(3)还有一些奇怪的地址也会出现异常,比如字符串中出现连续的两个“市”,输出会出现缺失。
输入:1!佘减觉,山东省枣庄市市中区13878001733大郭庄村216号大郭庄幼儿园.
输出:{"姓名":"佘减觉","手机":"13878001733","地址":["山东省","枣庄市","大","","郭庄村216号大郭庄幼儿园"]}
七、在PSP表格记录实际花费的时间
八、小结
说实话,从无到有的过程真是太坎坷了,现在凌晨三点,我啃了一个月饼续命。对于我来说主要的困难在主要于:
(1)对于需求分析不够透彻,走了很多弯路,带来了很多不必要的麻烦。
(2)学习一门新的语言Java。
(3)熟悉并掌握一些完全陌生的软件,比如eclpise,jProfiler,并且利用它们去进行程序的测试、分析。
(4)Github的上传,这太难了,难中难,困扰了我好久,我到现在都不知道我的程序能不能测评。
每天熬到两三点,我只觉得涂到脸上的精华都给这几天熬夜熬没了。但是苦尽甘来,收获还是蛮多的:
(1)大致了解了如何去规划完成一个程序的时间和步骤,以后
(2)做一件事情之前一定要看清需求,分析清楚怎么做以后,再着手去做。
(3)Java算是入了个门,也浅浅地掌握了正则表达式。
(4)对于eclipse和jProfiler也有了一定程度的熟悉度。
(5)大概了解了如何进行单元测试和性能分析。
有种开学胜期末的感觉, 累但是它值得。