AddressMatcher.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. package com.skyversation.poiaddr.util;
  2. import java.util.Arrays;
  3. import java.util.HashMap;
  4. import java.util.List;
  5. import java.util.Map;
  6. public class AddressMatcher {
  7. // 静态数据存储省市信息,包含简称映射
  8. private static final Map<String, List<String>> PROVINCE_CITY_MAP = new HashMap<>();
  9. private static final Map<String, String> ABBREVIATION_PROVINCE_MAP = new HashMap<>();
  10. private static final Map<String, String> ABBREVIATION_CITY_MAP = new HashMap<>();
  11. private static final Map<String, String> CITY_PROVINCE_MAP = new HashMap<>();
  12. static {
  13. // 初始化数据
  14. addProvinceAndCities("北京市", "东城区", "西城区", "朝阳区", "丰台区", "石景山区", "海淀区", "门头沟区", "房山区", "通州区", "顺义区", "昌平区", "大兴区", "怀柔区", "平谷区", "密云区", "延庆区");
  15. addProvinceAndCities("天津市", "和平区", "河东区", "河西区", "南开区", "河北区", "红桥区", "东丽区", "西青区", "津南区", "北辰区", "武清区", "宝坻区", "滨海新区", "宁河区", "静海区", "蓟州区");
  16. addProvinceAndCities("河北省", "石家庄市", "唐山市", "秦皇岛市", "邯郸市", "邢台市", "保定市", "张家口市", "承德市", "沧州市", "廊坊市", "衡水市");
  17. addProvinceAndCities("山西省", "太原市", "大同市", "阳泉市", "长治市", "晋城市", "朔州市", "晋中市", "运城市", "忻州市", "临汾市", "吕梁市");
  18. addProvinceAndCities("内蒙古自治区", "呼和浩特市", "包头市", "乌海市", "赤峰市", "通辽市", "鄂尔多斯市", "呼伦贝尔市", "巴彦淖尔市", "乌兰察布市");
  19. addProvinceAndCities("辽宁省", "沈阳市", "大连市", "鞍山市", "抚顺市", "本溪市", "丹东市", "锦州市", "营口市", "阜新市", "辽阳市", "盘锦市", "铁岭市", "朝阳市", "葫芦岛市");
  20. addProvinceAndCities("吉林省", "长春市", "吉林市", "四平市", "辽源市", "通化市", "白山市", "松原市", "白城市");
  21. addProvinceAndCities("黑龙江省", "哈尔滨市", "齐齐哈尔市", "鸡西市", "鹤岗市", "双鸭山市", "大庆市", "伊春市", "佳木斯市", "七台河市", "牡丹江市", "黑河市", "绥化市");
  22. addProvinceAndCities("上海市", "黄浦区", "徐汇区", "长宁区", "静安区", "普陀区", "虹口区", "杨浦区", "闵行区", "宝山区", "嘉定区", "浦东新区", "金山区", "松江区", "青浦区", "奉贤区", "崇明区");
  23. addProvinceAndCities("江苏省", "南京市", "无锡市", "徐州市", "常州市", "苏州市", "南通市", "连云港市", "淮安市", "盐城市", "扬州市", "镇江市", "泰州市", "宿迁市");
  24. addProvinceAndCities("浙江省", "杭州市", "宁波市", "温州市", "嘉兴市", "湖州市", "绍兴市", "金华市", "衢州市", "舟山市", "台州市", "丽水市");
  25. addProvinceAndCities("安徽省", "合肥市", "芜湖市", "蚌埠市", "淮南市", "马鞍山市", "淮北市", "铜陵市", "安庆市", "黄山市", "阜阳市", "宿州市", "滁州市", "六安市", "宣城市", "池州市", "亳州市");
  26. addProvinceAndCities("福建省", "福州市", "厦门市", "莆田市", "三明市", "泉州市", "漳州市", "南平市", "龙岩市", "宁德市");
  27. // addProvinceAndCities("江西省", "南昌市", "景德镇市", "萍乡市", "九江市", "新余市", "鹰潭市", "赣州市", "吉安市", "宜春市", "抚州市", "上饶市");
  28. addProvinceAndCities("江西省", "南昌市", "景德镇市", "萍乡市", "九江市", "鹰潭市", "赣州市", "吉安市", "宜春市", "抚州市", "上饶市");
  29. addProvinceAndCities("山东省", "济南市", "青岛市", "淄博市", "枣庄市", "东营市", "烟台市", "潍坊市", "济宁市", "泰安市", "威海市", "日照市", "临沂市", "德州市", "聊城市", "滨州市", "菏泽市");
  30. addProvinceAndCities("河南省", "郑州市", "开封市", "洛阳市", "平顶山市", "安阳市", "鹤壁市", "新乡市", "焦作市", "濮阳市", "许昌市", "漯河市", "三门峡市", "南阳市", "商丘市", "信阳市", "周口市", "驻马店市");
  31. addProvinceAndCities("湖北省", "武汉市", "黄石市", "十堰市", "宜昌市", "襄阳市", "鄂州市", "荆门市", "孝感市", "荆州市", "黄冈市", "咸宁市", "随州市");
  32. addProvinceAndCities("湖南省", "长沙市", "株洲市", "湘潭市", "衡阳市", "邵阳市", "岳阳市", "常德市", "张家界市", "益阳市", "郴州市", "永州市", "怀化市", "娄底市");
  33. // addProvinceAndCities("广东省", "广州市", "深圳市", "珠海市", "汕头市", "佛山市", "韶关市", "湛江市", "肇庆市", "江门市", "茂名市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市", "东莞市", "中山市", "潮州市", "揭阳市", "云浮市");
  34. addProvinceAndCities("广东省", "广州市", "深圳市", "珠海市", "汕头市", "佛山市", "韶关市", "湛江市", "肇庆市", "江门市", "茂名市", "惠州市", "梅州市", "汕尾市", "河源市", "阳江市", "清远市", "东莞市", "潮州市", "揭阳市", "云浮市");
  35. addProvinceAndCities("广西自治区", "南宁市", "柳州市", "桂林市", "梧州市", "北海市", "防城港市", "钦州市", "贵港市", "玉林市", "百色市", "贺州市", "河池市", "来宾市", "崇左市");
  36. addProvinceAndCities("海南省", "海口市", "三亚市", "三沙市", "儋州市");
  37. addProvinceAndCities("重庆市", "万州区", "黔江区", "涪陵区", "渝中区", "大渡口区", "江北区", "沙坪坝区", "九龙坡区", "南岸区", "北碚区", "綦江区", "大足区", "渝北区", "巴南区", "黔江区", "长寿区", "江津区", "合川区", "永川区", "南川区", "璧山区", "铜梁区", "潼南县", "荣昌区", "开州区", "梁平区", "武隆区", "城口县", "丰都县", "垫江县", "忠县", "云阳县", "奉节县", "巫山县", "巫溪县");
  38. addProvinceAndCities("四川省", "成都市", "自贡市", "攀枝花市", "泸州市", "德阳市", "绵阳市", "广元市", "遂宁市", "内江市", "乐山市", "南充市", "眉山市", "宜宾市", "广安市", "达州市", "雅安市", "巴中市", "资阳市");
  39. addProvinceAndCities("贵州省", "贵阳市", "六盘水市", "遵义市", "安顺市", "毕节市", "铜仁市");
  40. addProvinceAndCities("云南省", "昆明市", "曲靖市", "玉溪市", "保山市", "昭通市", "丽江市", "普洱市", "临沧市");
  41. addProvinceAndCities("西藏自治区", "拉萨市", "日喀则市", "昌都市", "林芝市", "山南市", "那曲市", "阿里地区");
  42. addProvinceAndCities("陕西省", "西安市", "铜川市", "宝鸡市", "咸阳市", "渭南市", "延安市", "汉中市", "榆林市", "安康市", "商洛市");
  43. addProvinceAndCities("甘肃省", "兰州市", "嘉峪关市", "金昌市", "白银市", "天水市", "武威市", "张掖市", "平凉市", "酒泉市", "庆阳市", "定西市", "陇南市");
  44. addProvinceAndCities("青海省", "西宁市", "海东市");
  45. addProvinceAndCities("宁夏自治区", "银川市", "石嘴山市", "吴忠市", "固原市", "中卫市");
  46. addProvinceAndCities("新疆自治区", "乌鲁木齐市", "克拉玛依市", "吐鲁番市", "哈密市");
  47. // 生成简称映射
  48. generateAbbreviations();
  49. // 生成城市到省份的映射
  50. generateCityProvinceMap();
  51. }
  52. private static void addProvinceAndCities(String province, String... cities) {
  53. PROVINCE_CITY_MAP.put(province, Arrays.asList(cities));
  54. }
  55. private static void generateAbbreviations() {
  56. for (String province : PROVINCE_CITY_MAP.keySet()) {
  57. String abbreviation = province.replaceAll("省|市|自治区", "");
  58. ABBREVIATION_PROVINCE_MAP.put(abbreviation, province);
  59. }
  60. for (Map.Entry<String, List<String>> entry : PROVINCE_CITY_MAP.entrySet()) {
  61. for (String city : entry.getValue()) {
  62. String abbreviation = city.replaceAll("市|区|县", "");
  63. ABBREVIATION_CITY_MAP.put(abbreviation, city);
  64. }
  65. }
  66. }
  67. private static void generateCityProvinceMap() {
  68. for (Map.Entry<String, List<String>> entry : PROVINCE_CITY_MAP.entrySet()) {
  69. String province = entry.getKey();
  70. for (String city : entry.getValue()) {
  71. CITY_PROVINCE_MAP.put(city, province);
  72. }
  73. }
  74. }
  75. /**
  76. * 根据输入的地址匹配省和市
  77. * @param address 输入的地址
  78. * @return 包含省和市的数组,若未匹配到则返回 null
  79. */
  80. public static String[] matchProvinceAndCity(String address) {
  81. // 先尝试匹配完整的省份名称
  82. for (String province : PROVINCE_CITY_MAP.keySet()) {
  83. if (address.contains(province)) {
  84. for (String city : PROVINCE_CITY_MAP.get(province)) {
  85. if (address.contains(city) &&!isPartOfRoadName(address, city)) {
  86. return new String[]{province, city};
  87. }
  88. }
  89. if (isMunicipality(province)) {
  90. return new String[]{province, province};
  91. }
  92. return new String[]{province, ""};
  93. }
  94. }
  95. // 尝试匹配省份简称
  96. for (Map.Entry<String, String> entry : ABBREVIATION_PROVINCE_MAP.entrySet()) {
  97. String abbreviation = entry.getKey();
  98. String province = entry.getValue();
  99. if (address.contains(abbreviation) &&!isPartOfRoadName(address, abbreviation)) {
  100. for (String city : PROVINCE_CITY_MAP.get(province)) {
  101. String cityAbbreviation = city.replaceAll("市", "");
  102. if (address.contains(cityAbbreviation) &&!isPartOfRoadName(address, cityAbbreviation)) {
  103. return new String[]{province, city};
  104. }
  105. }
  106. if (isMunicipality(province)) {
  107. return new String[]{province, province};
  108. }
  109. return new String[]{province, ""};
  110. }
  111. }
  112. // 尝试根据城市反向查找省份
  113. for (Map.Entry<String, String> entry : ABBREVIATION_CITY_MAP.entrySet()) {
  114. String cityAbbreviation = entry.getKey();
  115. String city = entry.getValue();
  116. if (address.contains(cityAbbreviation) &&!isPartOfRoadName(address, cityAbbreviation)) {
  117. String province = CITY_PROVINCE_MAP.get(city);
  118. if (province != null) {
  119. return new String[]{province, city};
  120. } else {
  121. return new String[]{"", city};
  122. }
  123. }
  124. }
  125. return null;
  126. }
  127. private static boolean isMunicipality(String province) {
  128. return province.equals("北京市") || province.equals("天津市") || province.equals("上海市") || province.equals("重庆市");
  129. }
  130. private static boolean isPartOfRoadName(String address, String name) {
  131. boolean is = address.contains(name + "路") || address.contains(name + "大道") || address.contains(name + "街");
  132. if(!is){
  133. int index = address.indexOf(name) + name.length();
  134. if("路道街".contains(address.substring((index + 1) >= address.length() ? address.length() - 1 : (index + 1),
  135. (index + 2) > address.length() ? address.length() : (index + 2)))){
  136. return true;
  137. }
  138. }
  139. return false;
  140. }
  141. public static void main(String[] args) {
  142. String address = "石家庄开封南路正定县新疆路123号";
  143. // String address = "上海静安南京南路123弄56号B座1204室";
  144. // String address = "河北石家庄正定县新疆路123号";
  145. // String address = "河北石家庄正定县新疆路123号";
  146. // String address = "河北石家庄正定县新疆路123号";
  147. // String address = "河北石家庄正定县新疆路123号";
  148. // String address = "河北石家庄正定县新疆路123号";
  149. String[] result = matchProvinceAndCity(address);
  150. if (result != null) {
  151. System.out.println("省: " + result[0]);
  152. System.out.println("市: " + result[1]);
  153. } else {
  154. System.out.println("未匹配到省和市");
  155. }
  156. }
  157. }