github仓库地址:
http://github.com/suweihuan079243/031702436]
PSP表格
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) |
---|---|---|
Planning | · 计划 | 1440 |
· Estimate | · 估计这个任务需要多少时间 | 1440 |
Development | · 开发 | 600 |
· Analysis | · 需求分析 (包括学习新技术) | 180 |
· Design Spec | · 生成设计文档 | 1440 |
· Design Review | · 设计复审 | 1440 |
· Coding Standard | · 代码规范 (为目前的开发制定合适的规范) | 30 |
· Design | · 具体设计 | 120 |
· Coding | · 具体编码) | 600 |
· Code Review | · 代码复审 | 60 |
· Test | · 测试(自我测试,修改代码,提交修改) | 180 |
· Reporting | · 报告 | |
· Test Repor | · 测试报告 | |
· Size Measurement | · 计算工作量 | |
· Postmortem & Process Improvement Plan | · 事后总结, 并提出过程改进计划 | 60 |
· | · 合计 | 7560 |
**# 预备知识学习* #* #
JSON
由于本次的输入输出需要使用到JSON,所以迫不得已去学习了一下,以下是我学习json的一些资源分享
https://blog.csdn.net/cpongo4/article/details/86613947JSON解析库MoShi学习
https://www.cnblogs.com/dmego/p/9033080.html FastJson的使用总结
2.正则表达式
需要利用正则表达式分割信息中的level、name、phoneNumber
这是在知乎上看到的github上的一个超过2w星的正则表达式学习项目
https://github.com/ziishaned/learn-regex
一个在线测试正则表达式的平台
https://regex101.com/
解题过程
本次编程作业的解题过程真的太难了(我太菜了),多亏我的一位热心同学全程给予我很多帮助,帮我配置gradle和教我git的使用(虽然我每次commit都是让他帮我弄),还有编程过程遇到的一些问题占用了他很多时间,非常感谢这位热心同学.
思路
- 由于涉及到杂乱字符串信息的提取,所以想到用正则表达式分割。
- 题目要求里有部分地址缺失,有点难定义一个完整的正则式来处理所有情况,所以想到通过全国 地图信息(省市县镇)来进行匹配。该地图为一个json文件,每级地址(除最后详细地址)下都有一个数组包含其下辖地址,通过逐级匹配来分割信息。
- 调用高德地图api,可惜不会。
设计实现过程
主要类
- 个人信息类Person
- 地图信息类MapData
- 分割信息工具类Trim
- Province类
- City类
- County类
- Town类
- Street类
主要函数 # :
- MapData.readMap():读取地图信息
- void Trim.setNewInformation(String information):读取个人信息
- void Trim.trimPhoneNumber():分割电话
- void Trim.trimLevel():分割等级和姓名
- void Trim.trimProvince():分割省份
- void Trim.trimCity(Province province):分割城市
- void Trim.trimCounty(City city):分割县级地区
- void Trim.trimTown(County county):分割镇级地区
- void Trim.trimStreet():分割镇以下地区
String Trim.trimInformation:去掉比较过的信息并返回新的信息
关键代码
public void trimProvince() {
try {
MapData.readMap();
} catch (IOException e) {
e.printStackTrace();
}
person.setName(this.personName);//初始化姓名
person.setPhoneNumber(this.phoneNumber);//初始化手机
// 福建福州市鼓楼区鼓西街道湖滨路110号湖滨大厦一层.
String provinceInformation = this.newInformation.substring(0, 2);//福建String provinceName =null;
for (Province province : MapData.getProvinces()) {
provinceName = province.getProvinceName().substring(0, 2);//福建
if (provinceInformation.equals(provinceName)) {if (provinceName.equals("北京") || provinceName.equals("重庆") ||
provinceName.equals("天津") ||provinceName.equals("上海")){
//
person.setProvince(province.getProvinceName());
} else {
person.setProvince(province.getProvinceName());
this.newInformation = trimInformation(this.newInformation, province.getProvinceName());
}
this.province=province;
break;
}
}
if(this.province!=null){
trimCity(this.province);
}else {
person.setProvince("""");
}
}
分割省份:先读取整个地图数据,截取信息的前两位用于省份匹配,遍历地图数据的省份,将provinceName与真实省名比较,如果相同则将信息与省名相同的部分去掉返回新的信息,并设置个人的省份,(ps:如果为直辖市,则只设置省份信息,方便后续用于城市信息的匹配),然后继续匹配城市。
if(this.city!=null){ trimCounty(this.city); }else{ person.setCity("\"\""); if(this.province!=null){ List
cityList = this.province.getCities(); for(City city:cityList){ trimCounty(city); } } } 由于城市以下的地址可能为空,所以匹配完进行判断。如果不为空继续判断,否则通过去遍历此
省份的所有城市去匹配其下辖的县级地区,后面类似。private void trimStreet() { if (this.level == 1) { person.setRestAddress(this.newInformation);//五级地址直接将镇以下赋值 } else if (this.level == 2 || level == 3) { String regex1 = "(\\D+)(\\d+号)";//匹配路名和门牌号 Pattern pattern = Pattern.compile(regex1); Matcher matcher = pattern.matcher(newInformation); String restAddress = null; if (matcher.find()) { restAddress = matcher.replaceFirst(""); this.newInformation = matcher.group(); String regex2 = "\\d+号"; String gateNumber = null; String roadName = null; Pattern pattern1 = Pattern.compile(regex2); Matcher matcher1 = pattern1.matcher(this.newInformation); if (matcher1.find()) { gateNumber = matcher1.group(0);//匹配门牌号 roadName = matcher1.replaceAll("");//匹配路名 } if(roadName!=null){ person.setRoadName(roadName); }else { person.setRoadName("\"\""); } if(gateNumber!=null){ person.setGateNumber(gateNumber); }else{ person.setGateNumber("\"\""); } if(restAddress!=null){ person.setRestAddress(restAddress); }else{ person.setRestAddress("\"\""); } } }
根据等级处理镇以下的地址信息,如果level=1,直接将镇以下的地址信息全部输出;如果是level2&level3,就继续利用正则分割为路、门牌号、详细地址(虽然我不知道是不是所有例子的门牌号都是以号结尾)
性能分析
说真的我看不懂更别说改进了,能有结果就不错了
异常处理说明
@Test
public void testTrimLevel(){
Trim trim=new Trim();
trim.setNewInformation("1!宗衬缝,湖南省长沙市浏阳市古港镇024乡道古港镇梅田湖村村民委员15590409121会.");
trim.trimLevel();
System.out.println(trim.getLevel());
}
public void trimLevel() {
String regexLevel = "[!,]";
String[] split = this.newInformation.split(regexLevel);
this.level = split[0];
personName = split[1];
this.newInformation = split[2];
person.setName(this.personName);
}
一开始level定义为int类型,截取后通过Integer.parseInt()转为int类型,后面改来改去不知道为什么就会出现NumberformatException,找了半天找不到原因。就只好level定义为String类型就好了。
try {
MapData.readMap();
} catch (IOException e) {
e.printStackTrace();
}
String provinceInformation = this.newInformation.substring(0, 2);
List provinceList = MapData.getProvinces();
**for (Province province : provinceList) **
一开始每级的分割地址*号部分经常出现nullpointerexception,原因是忘了先读取地图。