最近有个需求需要解析用户的地址,在网上翻了不少,结合用户的一些地址习惯改了下,主要是针对,直辖市进行了更改(ps:大部分人直辖市只会写一次市 北京市朝阳区XXX类似这样,但是网上大多是 对于北京市北京市朝阳区这类才能进行解析).不多说了上代码:

package com.test;

import org.apache.commons.lang.StringUtils;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class addressSpiltTest {

    public static void main(String[] args) {
        List<String> addresses = new ArrayList<>();
        addresses.add("北京市朝阳区国家会议中心");
        addresses.add("北京朝阳区");
        addresses.add("广东省深圳市南山区深云村");
        addresses.add("深圳市南山区南山大道光大村");
        addresses.add("深圳南山巴啦啦");
        addresses.add("深圳南山区啦啦啦");
        addresses.add("香港");
        addresses.add("北京朝阳啦啦啦");
        addresses.add("上海市真华路XX弄XX号XXX室");
        addresses.add("天津市汉沽区明城北岸XXX");
        addresses.add("广东省开平市新昌新安路XXXX");
        addresses.add("湖南省郴州市临武县舜峰镇两路交叉口");
        addresses.add("广东省广州市六运X街X号XXX");
        addresses.add("广东省广州市黄浦区测试小区2栋");
        addresses.add("香港九龙XXXXX");
        for(int i=0; i<addresses.size(); i++) {
            String address = addresses.get(i);
            String province = "不详";
            String city = "不详";
            String town = "不详";
            String detailAddress = "不详";
            List<Map<String, String>> addressList = addressResolution(address);
            if (addressList != null && addressList.size()>0) {
                if (StringUtils.isNotBlank(addressList.get(0).get("province"))) {
                    province = addressList.get(0).get("province");
                }
                if (StringUtils.isNotBlank(addressList.get(0).get("city"))) {
                    city = addressList.get(0).get("city");
                    if (city.equals("上海市") || city.equals("重庆市") || city.equals("北京市") || city.equals("天津市")) {
                        province = addressList.get(0).get("city");
                    }
                }else if(province.equals("上海市") || province.equals("重庆市") || province.equals("北京市") || province.equals("天津市")) {
                    city = province;
                }
                if (StringUtils.isNotBlank(addressList.get(0).get("town"))) {
                    town = addressList.get(0).get("town");
                }
                if (StringUtils.isNotBlank(addressList.get(0).get("detailAddress"))) {
                    detailAddress = addressList.get(0).get("detailAddress");
                }
            }else{
                System.out.println("地址不符合要求");
            }
            System.out.println(address);
            System.out.println("province:" + province + "city:" + city + "town:" + town + "detailAddress:" + detailAddress);
        }
    }

    /**
     * 解析地址
     * @param address
     * @return
     */
    public static List<Map<String,String>> addressResolution(String address){
        //特殊:特别行政区 台湾省
        //1级 省 自治区  2级 市 自治州 地区 3级:区县市旗(镇?)
        String province=null,city=null,provinceAndCity=null,town=null,detailAddress=null;
        Map<String,String> row = new LinkedHashMap<String,String>();;
        List<Map<String,String>> table=new ArrayList<Map<String,String>>();
        if(address.contains("特别行政区")){
            //特殊处理
        }else if(address.contains("香港")){
            //特殊处理
        }else if(address.contains("澳门")){
            //特殊处理
        }else if(address.contains("台湾")){
            //特殊处理
        } else{
            //普通地址
            String regex="((?<provinceAndCity>[^市]+市|.*?自治州)(?<town>[^县]+县|.*?区|.*?镇|.*?市|.*?旗)(?<detailAddress>.*))";
            Matcher m=Pattern.compile(regex).matcher(address);
            while(m.find()){
                provinceAndCity=m.group("provinceAndCity");
                String regex2 = "((?<province>[^省]+省|.+自治区|上海市|北京市|天津市|重庆市|上海|北京|天津|重庆)(?<city>.*))";
                Matcher m2=Pattern.compile(regex2).matcher(provinceAndCity);
                while(m2.find()){
                    province=m2.group("province");
                    row.put("province", province==null?"":province.trim());
                    city=m2.group("city");
                    row.put("city", city==null?"":city.trim());
                }
                town=m.group("town");
                row.put("town", town==null?"":town.trim());
                detailAddress=m.group("detailAddress");
                row.put("detailAddress", detailAddress==null?"":detailAddress.trim());
                table.add(row);
            }
        }
        return table;
    }
}

 

  运行结果:

北京市朝阳区国家会议中心
province:北京市city:北京市town:朝阳区detailAddress:国家会议中心
地址不符合要求
北京朝阳区
province:不详city:不详town:不详detailAddress:不详
广东省深圳市南山区深云村
province:广东省city:深圳市town:南山区detailAddress:深云村
深圳市南山区南山大道光大村
province:不详city:不详town:南山区detailAddress:南山大道光大村
地址不符合要求
深圳南山巴啦啦
province:不详city:不详town:不详detailAddress:不详
地址不符合要求
深圳南山区啦啦啦
province:不详city:不详town:不详detailAddress:不详
地址不符合要求
香港
province:不详city:不详town:不详detailAddress:不详
地址不符合要求
北京朝阳啦啦啦
province:不详city:不详town:不详detailAddress:不详
地址不符合要求
上海市真华路XX弄XX号XXX室
province:不详city:不详town:不详detailAddress:不详
天津市汉沽区明城北岸XXX
province:天津市city:天津市town:汉沽区detailAddress:明城北岸XXX
地址不符合要求
广东省开平市新昌新安路XXXX
province:不详city:不详town:不详detailAddress:不详
湖南省郴州市临武县舜峰镇两路交叉口
province:湖南省city:郴州市town:临武县detailAddress:舜峰镇两路交叉口
地址不符合要求
广东省广州市六运X街X号XXX
province:不详city:不详town:不详detailAddress:不详
广东省广州市黄浦区测试小区2栋
province:广东省city:广州市town:黄浦区detailAddress:测试小区2栋
地址不符合要求
香港九龙XXXXX
province:不详city:不详town:不详detailAddress:不详

 

总结:  可以看出类似于广东省广州市测试小区2栋这种,或者 前匹配乱写能匹配上省市区的都无法发现其问题,但是业务上不存在这种,欢迎有意见以及改进。技术有限,欢迎纠错。

 

2020/1/9 使用中发现 类似于 XX省XX市XX镇XXXXXX小区 这种地址 由于 按照正则匹配排序上区比镇在前面会有问题相似的情况也会有这个问题,由于正则这块不太熟,欢迎提供解决方案