作业GitHub
PSP Table
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 60 | 60 |
Estimate | 估计这个任务需要多少时间 | 60 | 60 |
Development | 开发 | 830 | 1175 |
Analysis | 需求分析 (包括学习新技术) | 120 | 150 |
Design Spec | 生成设计文档 | 30 | 45 |
Design Review | 设计复审 | 30 | 25 |
Coding Standard | 代码规范 (为目前的开发制定或选择合适的规范) | 20 | 30 |
Design | 具体设计 | 120 | 100 |
Coding | 具体编码 | 240 | 480 |
Code Review | 代码复审 | 60 | 75 |
Test | 测试(自我测试,修改代码,提交修改) | 210 | 270 |
Reporting | 报告 | 60 | 80 |
Test Repor | 测试报告 | 20 | 40 |
Size Measurement | 计算工作量 | 10 | 10 |
Postmortem & Process Improvement Plan | 事后总结, 并提出改进计划 | 30 | 30 |
合计 | 950 | 1315 |
Solution
- 对于姓名与电话号码用正则表达式[1]直接提取出,在信息中删除姓名、电话号码和其他一些无关紧要的逗号等字符,避免扰乱地址信息的判断与拆分。
- 取出地址信息后,对于能够正确使用正则表达式拆分的地址采取直接拆分并获取各级地址信息。
- 对于无法直接拆分,即缺字眼或者缺少某一级的地址,则调用高德 API[2]对地址缺失部分进行查询并补全,再进行正则拆分。这里存在着网络上的延迟,因为实在不想打表,要处理好多各级地址的名字以及它们的存取、查询以及判断的方法,所以只好调用API。
Implement
本次作业使用的程序设计语言为Java
WebApiReturnAddress类中函数Map
WebApiAddress(String ad):通过调用高德地图api获取地址。为了保证该类的正常使用,需要额外运用到的外部包有: ① commons-beanutils-1.7.0.jar
② commons-collections-3.1.jar
③ commons-lang-2.5.jar
④ commons-logging.jar
⑤ ezmorph-1.0.3.jar
⑥ json-lib-2.4-jdk15.jarRegular_Split类中函数List
Java正则表达式的使用是通过java.util.regex包下的Pattern类与Matcher类配合实现[3][4]。
主要的正则表达式为:参考[5]
"(? [^省]+自治区|.*?省|.*?行政区|.*?市)(? [^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县|.*?直辖市)(? [^县]+?县|.+?区|.+?县级市|.+?旗|.+?海域|.+?岛)?(? [^乡]+乡|.+街道|.+镇|)?(? .*)"Regex_Split_Seven类中函数List
通过网上调查,5级与6级的命名大多存在:路、胡同、街、巷、道、里、弄、坊、台、市以及、号、道。故正则表达式为:
"(? [^路]+胡同|.*?路|.*?街|.*?巷|.*?道|.*?里|.*?弄|.*?坊|.*?台|.*?市)(? [^号]+号|.*?号|.*?道)?(? .*)"Address_Partition4类是main函数所在之处。它主要进行类别分析、名字与电话号码的匹配、调度上文所述的三个类、细分地址详细信息以及直辖市的判断。
函数ReturnDetailsIndex(String s):返回地址最细致一级的开头(index),配合substring()函数,可以切出存在于地址中几乎最详细的一级。
函数checkstring(String s):可以判别地址是否属于直辖市地址。
使用BufferedReader与BufferedWriter类提高读写速度。
总体框架:
Class Name | Method Name | Implement |
---|---|---|
Address_Partition4 | main(String[] args) | 主函数,args[0]为文件输入,args[1]为文件输出 |
ReturnDetailsIndex(String s) | 找到详细地址的上一级 | |
checkstring(String s) | 判断直辖市 | |
Regex_Split | Address_Regex_Split(String address) | 5级地址规则的4级匹配划分 |
Regex_Split_Seven | Address_Seven_Split(String address) | 7级地址规则的5,6级匹配划分 |
WebApiReturnAddress | WebApiAddress(String ad) | 调用高德API |
Performance
环境:IDEA11.0.3 + JProfiler
方法Call Tree:
可以清楚的看出,最主要的时间都消耗在WebApiReturnAddress类中。再来看看类的Call Tree分析图:
造成这种情况的原因其实是非常容易明白:通过网络调用就会存在网络延迟,这几乎是由服务器与客户端的距离(传输时延)所造成的,是无法避免的。
类的Live Memory:
从图中可以看出,字符数组和字符串类型占用内存较大,这也是这道题处理难度的所在之处。既然是文本处理,自然是对字符以及字符串处理。反而对于花费时间最多的网络调用相关类却没有明显的内存开销。
方法的CPU Hot Spot:
类的CPU Hot Spot:
以上可以看出,本次程序主要的非内存资源都花费在网络服务。能改进的地方,我觉得是可以利用本地的四级联动数据代替网络服务,但是由于尚未实现,无法比较两者的差距。
UnitTest
测试用例:
2!李四,福建省福州13756899511市鼓楼区鼓西街道湖滨路110号湖滨大厦一层.
1!张三,福建福州闽13599622362侯县上街镇福州大学10#111.
2!王五,福建省福州市鼓楼18960221533区五一北路123号福州鼓楼医院.
3!小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院.
1!小陈,广东省东莞市凤岗13965231525镇凤平路13号.
1!支悦,福建福州15607517635福飞南路心连心金融大厦.
2!陈伯茂,15305810259,福建省福州市鼓屏路67号福建省级机关医院.
3!容丹,福建15807458350仓房街古波廊6号乐途居客栈.
3!广苑茜,上海15707725273亭枫公路253号金山巴士亭林汽车站.
2!王五,云南省水富18694520738县云川路1号水富火车站货运大楼.
1!万琦,广东深13805204711圳福强路1031福民新村.
3!红宜君,北京市东三15005824713环南路88号佳兆业·王府世纪.
1!陈利,广西13006154923南宁市青秀区建政街道方园路1号方园公寓1区.
2!党聪莉,15705217077,湖北省武汉市车城北路58号武汉体育中心.
3!王五,四川仁寿18694520738县黑龙滩镇牌坊街小廖副食.
1!陈杰,13215900209,四川眉山大南街50号中岩大酒店.
1!季波,重庆13707600542南岸区铜元局正街金辉·春上南滨.
2!澹晶,13907836232成都青羊区西华门街17号天府中心.
所得结果:
[
{
"姓名":"李四",
"手机":"13756899511",
"地址":[
"福建省",
"福州市",
"鼓楼区",
"鼓西街道",
"湖滨路",
"110号",
"湖滨大厦一层"
]
},
{
"姓名":"张三",
"手机":"13599622362",
"地址":[
"福建省",
"福州市",
"闽侯县",
"上街镇",
"福州大学10#111"
]
},
{
"姓名":"王五",
"手机":"18960221533",
"地址":[
"福建省",
"福州市",
"鼓楼区",
"",
"五一北路",
"123号",
"福州鼓楼医院"
]
},
{
"姓名":"小美",
"手机":"15822153326",
"地址":[
"北京",
"北京市",
"东城区",
"",
"交道口东大街",
"1号",
"北京市东城区人民法院"
]
},
{
"姓名":"小陈",
"手机":"13965231525",
"地址":[
"广东省",
"东莞市",
"",
"凤岗镇",
"凤平路13号"
]
},
{
"姓名":"支悦",
"手机":"15607517635",
"地址":[
"福建省",
"福州市",
"晋安区",
"",
"福飞南路心连心金融大厦"
]
},
{
"姓名":"陈伯茂",
"手机":"15305810259",
"地址":[
"福建省",
"福州市",
"鼓楼区",
"",
"鼓屏路",
"67号",
"福建省级机关医院"
]
},
{
"姓名":"容丹",
"手机":"15807458350",
"地址":[
"福建省",
"福州市",
"鼓楼区",
"",
"仓房街",
"古波廊6号",
"乐途居客栈"
]
},
{
"姓名":"广苑茜",
"手机":"15707725273",
"地址":[
"上海",
"上海市",
"金山区",
"",
"亭枫公路",
"253号",
"金山巴士亭林汽车站"
]
},
{
"姓名":"王五",
"手机":"18694520738",
"地址":[
"云南省",
"",
"水富县",
"",
"云川路",
"1号",
"水富火车站货运大楼"
]
},
{
"姓名":"万琦",
"手机":"13805204711",
"地址":[
"广东省",
"深圳市",
"福田区",
"",
"福强路1031福民新村"
]
},
{
"姓名":"红宜君",
"手机":"15005824713",
"地址":[
"北京",
"北京市",
"朝阳区",
"",
"东三环南路",
"88号",
"佳兆业·王府世纪"
]
},
{
"姓名":"陈利",
"手机":"13006154923",
"地址":[
"广西壮族自治区",
"南宁市",
"青秀区",
"建政街道",
"方园路1号方园公寓1区"
]
},
{
"姓名":"党聪莉",
"手机":"15705217077",
"地址":[
"湖北省",
"武汉市",
"蔡甸区",
"",
"车城北路",
"58号",
"武汉体育中心"
]
},
{
"姓名":"王五",
"手机":"18694520738",
"地址":[
"四川省",
"眉山市",
"仁寿县",
"黑龙滩镇",
"牌坊街",
"",
"小廖副食"
]
},
{
"姓名":"陈杰",
"手机":"13215900209",
"地址":[
"四川省",
"眉山市",
"丹棱县",
"",
"大南街50号中岩大酒店"
]
},
{
"姓名":"季波",
"手机":"13707600542",
"地址":[
"重庆",
"重庆市",
"南岸区",
"",
"铜元局正街金辉·春上南滨"
]
},
{
"姓名":"澹晶",
"手机":"13907836232",
"地址":[
"四川省",
"成都市",
"青羊区",
"",
"西华门街",
"17号",
"天府中心"
]
}
]
Exception Process
- 只有姓名与电话号码,没有地址信息:
3!甫永,15600806319 - 姓名没有与地址信息分开:
3!13400271954,司亮福建仓房街古波廊6号乐途居客栈 - 输入信息没有进行分级:
小美,北京市东15822153326城区交道口东大街1号北京市东城区人民法院.
Summary
- 测数据比打码还累。
- 学会了JProfiler的简单用法。
- UTF-8有点坑,打包被安排。为了用gradle打出带依赖包的JAR,从eclipse跳到idea。
- 原来中国真的好大,各种行政区地级市名字玩得这么花。
- 很多可能出现异常的地方没有处理,只是简单地抛出。
- 我好菜。