【Java 解析全国地址】Java 利用正则表达式完美解析全国省市区地址

Java 利用正则表达式完美解析全国省市区地址

一、问题场景描述

最近在项目中遇到了一个全国地址解析的一个场景,前端会传来一个字符串,后端需自动解析出 xx省xx市xx区+详细地址 的这种格式。

因为我们的数据来源于其他系统,客户地址在其他系统可能是随便填的,并不是正确的,所以前端也做了支持更改地址的操作。所以,我们的地址解析方式也是根据前端的地址格式来进行解析的。

二、解决方案

我也是第一次遇到这个场景,于是首先百度了一手,得到的解决方案有:

  1. 根据正则表达式进行解析;
    1. https://blog.csdn.net/superSubfn/article/details/80290491
    2. https://blog.csdn.net/weixin_44590872/article/details/108470804
  2. 字符串匹配遍历的方式;
    1. https://juejin.cn/post/6969820144927244324
    2. https://blog.csdn.net/renfng/article/details/94738164

tips: 还有其他的解决方案,已经找不到网址了,就不贴了

根据我们的这个业务需求,用正则是比较方便的,因为我们前端会有地址的固定格式,比如:江苏省南京市雨花台区某某地址,对于这段字符串,只要成功匹配出省、市、区就可以完成地址的解析。

三、开发过程中遇到的问题

我一开始是直接用了百度的正则,这个正则表达式,可以解析出正常的省市区地址,但是对于北京市这种直辖市和香港行政区这些地方没有做很好的匹配。于是,根据前端的地址选项做出了正则的更改。

前端的地址选项格式:

在这里插入图片描述

前端对于北京上海这类直辖市,的格式:北京市北京市西城区xx地址

// 百度到的正则
String regex="(?<province>[^省]+自治区|.*?省|.*?行政区|.*?市)(?<city>[^市]+自治州|.*?地区|.*?行政单位|.+盟|市辖区|.*?市|.*?县)(?<county>[^县]+县|.+区|.+市|.+旗|.+海域|.+岛)?(?<town>[^区]+区|.+镇)?(?<village>.*)";
// 修改后的正则
String regex = "(?<province>[^省]+省|.+自治区|[^澳门]+澳门|[^香港]+香港|[^市]+市)?(?<city>[^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+县)(?<county>[^县]+县|[^市]+市|[^镇]+镇|[^区]+区|[^乡]+乡|.+场|.+旗|.+海域|.+岛)?(?<address>.*)";

四、应用代码

1、地址封装类

@Data
@NoArgsConstructor
public class WSSsdrAddress implements Serializable {
		
    private String province;

    private String city;

    private String county;

    private String address;

    public WSSsdrAddress(String province, String city, String county, String address) {
        if (StringUtils.isBlank(province) ||
                StringUtils.isBlank(city) ||
                StringUtils.isBlank(county) ||
                StringUtils.isBlank(address)) {
            throw new BaseException("客户联系地址出错");
        }
        this.province = province;
        this.city = city;
        this.county = county;
        this.address = address;
    }
}

2、地址解析工具类

更新:鉴于之前的正则解析成功率不是很高,对正则进行优化,可以使用如下正则表达式替工具类中的正则

        String regex = "^(?<province>[^市县区]+(?:省|自治区|特别行政区))(?<city>[^市县区]+市|市辖区)(?<county>[^市县区]+(?:区|县|市内区|林区|特区))?(?<address>(?:[^\\n]*))$";

public class AddressUtil {

    private AddressUtil() {}

    /**
     * 从地址串中解析提取出省市区等信息
     * @param address   地址信息
     * @return          解析后的地址Map
     */
    private static Map<String,String> addressResolution(String address){
        //1.地址的正则表达式
		String regex = "(?<province>[^省]+省|.+自治区|[^澳门]+澳门|[^香港]+香港|[^市]+市)?(?<city>[^自治州]+自治州|[^特别行政区]+特别行政区|[^市]+市|.*?地区|.*?行政单位|.+盟|市辖区|[^县]+县)(?<county>[^县]+县|[^市]+市|[^镇]+镇|[^区]+区|[^乡]+乡|.+场|.+旗|.+海域|.+岛)?(?<address>.*)";
        //2、创建匹配规则
        Matcher m = Pattern.compile(regex).matcher(address);
        String province;
        String city;
        String county;
        String detailAddress;
        Map<String,String> map = new HashMap<>(16);

        while (m.find()){
            //加入省
            province = m.group("province");
            map.put("province", province == null ? "" : province.trim());
            //加入市
            city = m.group("city");
            map.put("city", city == null ? "" : city.trim());
            //加入区
            county = m.group("county");
            map.put("county", county == null ? "" : county.trim());
            //详细地址
            detailAddress = m.group("address");
            map.put("address", detailAddress == null ? "" : detailAddress.trim());
        }
        return map;
    }

    /**
     * 根据地址获取解析后的地址对象
     * @param address   解析前地址Str
     * @return          解析后地址对象
     */
    public static WSSsdrAddress resolveAddress(String address) {
        if (CharSequenceUtil.isBlank(address)) {
            throw new BaseException("客户联系地址出错");
        }
        Map<String, String> addressMap = addressResolution(address);
        return new WSSsdrAddress(addressMap.get("province"), addressMap.get("city"), addressMap.get("county"), addressMap.get("address"));
    }

}

3、测试结果

下面的测试应该包含了全国90%以上稀奇古怪的区域名了:

在这里插入图片描述

五、附件

我们的项目是搭配着前端提供的省市区进行解析的,在此附上前端使用的全国省市区json:https://github.com/getActivity/ProvinceJson/blob/master/province.json

如果帮助到了你,或者觉得有用,不妨点个赞?

参考文章:

  1. https://blog.csdn.net/superSubfn/article/details/80290491
  2. https://blog.csdn.net/weixin_44590872/article/details/108470804
  • 28
    点赞
  • 58
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值