AddressMatcher.java 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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. // 生成简称映射
  46. generateAbbreviations();
  47. // 生成城市到省份的映射
  48. generateCityProvinceMap();
  49. }
  50. private static void addProvinceAndCities(String province, String... cities) {
  51. PROVINCE_CITY_MAP.put(province, Arrays.asList(cities));
  52. }
  53. private static void generateAbbreviations() {
  54. for (String province : PROVINCE_CITY_MAP.keySet()) {
  55. String abbreviation = province.replaceAll("省|市|自治区", "");
  56. ABBREVIATION_PROVINCE_MAP.put(abbreviation, province);
  57. }
  58. for (Map.Entry<String, List<String>> entry : PROVINCE_CITY_MAP.entrySet()) {
  59. for (String city : entry.getValue()) {
  60. String abbreviation = city.replaceAll("市|区|县", "");
  61. ABBREVIATION_CITY_MAP.put(abbreviation, city);
  62. }
  63. }
  64. }
  65. private static void generateCityProvinceMap() {
  66. for (Map.Entry<String, List<String>> entry : PROVINCE_CITY_MAP.entrySet()) {
  67. String province = entry.getKey();
  68. for (String city : entry.getValue()) {
  69. CITY_PROVINCE_MAP.put(city, province);
  70. }
  71. }
  72. }
  73. /**
  74. * 根据输入的地址匹配省和市
  75. *
  76. * @param address 输入的地址
  77. * @return 包含省和市的数组,若未匹配到则返回 null
  78. */
  79. public static String[] matchProvinceAndCity(String address) {
  80. // 先尝试匹配完整的省份名称
  81. for (String province : PROVINCE_CITY_MAP.keySet()) {
  82. if (address.contains(province)) {
  83. for (String city : PROVINCE_CITY_MAP.get(province)) {
  84. if (address.contains(city) && !isPartOfRoadName(address, city)) {
  85. return new String[]{province, city};
  86. }
  87. }
  88. if (isMunicipality(province)) {
  89. return new String[]{province, province};
  90. }
  91. return new String[]{province, ""};
  92. }
  93. }
  94. // 尝试匹配省份简称
  95. for (Map.Entry<String, String> entry : ABBREVIATION_PROVINCE_MAP.entrySet()) {
  96. String abbreviation = entry.getKey();
  97. String province = entry.getValue();
  98. if (address.contains(abbreviation) && !isPartOfRoadName(address, abbreviation)) {
  99. for (String city : PROVINCE_CITY_MAP.get(province)) {
  100. String cityAbbreviation = city.replaceAll("市", "");
  101. if (address.contains(cityAbbreviation) && !isPartOfRoadName(address, cityAbbreviation)) {
  102. return new String[]{province, city};
  103. }
  104. }
  105. if (isMunicipality(province)) {
  106. return new String[]{province, province};
  107. }
  108. return new String[]{province, ""};
  109. }
  110. }
  111. // 尝试根据城市反向查找省份
  112. for (Map.Entry<String, String> entry : ABBREVIATION_CITY_MAP.entrySet()) {
  113. String cityAbbreviation = entry.getKey();
  114. String city = entry.getValue();
  115. if (address.contains(cityAbbreviation) && !isPartOfRoadName(address, cityAbbreviation)) {
  116. String province = CITY_PROVINCE_MAP.get(city);
  117. if (province != null) {
  118. return new String[]{province, city};
  119. } else {
  120. return new String[]{"", city};
  121. }
  122. }
  123. }
  124. return null;
  125. }
  126. private static boolean isMunicipality(String province) {
  127. return province.equals("北京市") || province.equals("天津市") || province.equals("上海市") || province.equals("重庆市");
  128. }
  129. /**
  130. * 只有返回为false时,才会检验成功
  131. *
  132. * @param address
  133. * @param name
  134. * @return
  135. */
  136. private static boolean isPartOfRoadName(String address, String name) {
  137. boolean is = address.contains(name + "路") || address.contains(name + "大道") || address.contains(name + "街") || address.contains(name + "社区") || address.contains("镇江");
  138. if (!is) {
  139. int index = address.indexOf(name) + name.length();
  140. String endStr = address.substring(index, Math.min((index + 2), address.length()));
  141. if (endStr.contains("路") || endStr.contains("道") || endStr.contains("街")) {
  142. return true;
  143. } else {
  144. is = false;
  145. }
  146. }
  147. return is;
  148. }
  149. public static void main(String[] args) {
  150. String address = "石家庄开封南路正定县新疆路123号";
  151. String[] result = matchProvinceAndCity(address);
  152. if (result != null) {
  153. System.out.println("省: " + result[0]);
  154. System.out.println("市: " + result[1]);
  155. } else {
  156. System.out.println("未匹配到省和市");
  157. }
  158. }
  159. }