Java實(shí)現(xiàn)根據(jù)地址智能識(shí)別省市區(qū)縣
一、需求
根據(jù)OCR識(shí)別出的身份證地址或者用戶輸入的地址,智能識(shí)別出用戶的省、市、區(qū)/縣和詳細(xì)地址信息。
二、思路
解析給到接口的完整地址fullAddress,逐個(gè)匹配省province、市city、區(qū)/縣area、詳細(xì)地址detail,然后將 province+city+area+detail 返回即可。
PS:需要考慮一些情況:
1、四個(gè)直轄市(北京市、上海市、天津市、重慶市)。直轄市的完整地址fullAddress只有省、縣/區(qū)
2、完整地址fullAddress只有省、區(qū)/縣
3、市與區(qū)/縣重名
4、區(qū)/縣與區(qū)/縣重名
三、實(shí)現(xiàn)代碼
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 身份證信息分析工具類Util
*/
@Slf4j
public class AnalysisIdCardUtil {
/**
* 獲取詳細(xì)地址
*
* @param fullAddress 身份證完整地址
*/
public static String getDetailedAddress(String fullAddress) {
String[] addressArrays = spliceDetailedAddress(fullAddress);
return addressArrays[addressArrays.length - 1];
}
/**
* 獲取省市區(qū)地址,如:安徽省合肥市包河區(qū)
*
* @param fullAddress 身份證完整地址
*/
public static String getPcaAddress(String fullAddress) {
String[] addressArrays = spliceDetailedAddress(fullAddress);
StringBuilder areaBuffer = new StringBuilder();
for (int i = 0; i < addressArrays.length - 1; i++) {
if (StringUtils.isNotEmpty(addressArrays[i])) {
areaBuffer.append(addressArrays[i]);
}
}
return areaBuffer.toString();
}
/**
* 身份證完成地址拆分為[省、市、區(qū)、詳細(xì)地址]數(shù)組,如:[安徽省, 合肥市, 包河區(qū), 幸福大街001號(hào)]
*
* @param fullAddress 身份證完整地址
*/
public static String[] spliceDetailedAddress(String fullAddress) {
String[] arr = new String[4];
try {
String tempStr = fullAddress;
// 省
String province = null;
int provinceIdx = processProvince(tempStr);
if (provinceIdx > -1) {
province = tempStr.substring(0, provinceIdx + 1);
tempStr = tempStr.substring(provinceIdx + 1);
}
// 市
String city = null;
int cityIdx = processCity(tempStr);
if (cityIdx > -1) {
city = tempStr.substring(0, cityIdx + 1);
tempStr = tempStr.substring(cityIdx + 1);
}
// 區(qū)
String county = null;
int countyIdx = processCounty(tempStr);
if (countyIdx > -1) {
county = tempStr.substring(0, countyIdx + 1);
tempStr = tempStr.substring(countyIdx + 1);
}
String street = tempStr;
arr[0] = province;
arr[1] = city;
arr[2] = county;
arr[3] = street;
} catch (Exception e) {
log.error("身份證詳細(xì)地址轉(zhuǎn)義失?。簕}", e.getMessage());
}
return arr;
}
/**
* 拆分身份證完整地址中的省份信息
*
* @param address 地址
*/
private static int processProvince(String address) {
int[] idx = new int[3];
int provinceIdx;
if ((provinceIdx = address.indexOf("省")) > -1) {
idx[0] = provinceIdx;
}
if ((provinceIdx = address.indexOf("市")) > -1) {
idx[1] = provinceIdx;
}
if ((provinceIdx = address.indexOf("區(qū)")) > -1) {
idx[2] = provinceIdx;
}
Arrays.sort(idx);
for (int j : idx) {
if (j > 0) {
return j;
}
}
return provinceIdx;
}
/**
* 拆分身份證完整地址中的市區(qū)/縣/自治州信息
*
* @param address 地址
*/
private static int processCity(String address) {
int[] idx = new int[7];
int cityIdx = -1;
if ((cityIdx = address.indexOf("縣")) > -1) {
idx[0] = cityIdx;
}
if ((cityIdx = address.indexOf("自治州")) > -1) {
idx[1] = cityIdx + 2;
}
if ((cityIdx = address.indexOf("市轄區(qū)")) > -1) {
idx[2] = cityIdx + 2;
}
if ((cityIdx = address.indexOf("市")) > -1) {
idx[3] = cityIdx;
}
if ((cityIdx = address.indexOf("區(qū)")) > -1) {
idx[4] = cityIdx;
}
if ((cityIdx = address.indexOf("地區(qū)")) > -1) {
idx[5] = cityIdx + 1;
}
if ((cityIdx = address.indexOf("盟")) > -1) {
idx[6] = cityIdx;
}
Arrays.sort(idx);
for (int j : idx) {
if (j > 0) {
return j;
}
}
return cityIdx;
}
/**
* 拆分身份證完整地址中的縣/旗/島信息
*
* @param address 地址
*/
private static int processCounty(String address) {
int[] idx = new int[6];
int countyIdx;
if ((countyIdx = address.indexOf("縣")) > -1) {
idx[0] = countyIdx;
}
if ((countyIdx = address.indexOf("旗")) > -1) {
idx[1] = countyIdx;
}
if ((countyIdx = address.indexOf("海域")) > -1) {
idx[2] = countyIdx + 1;
}
if ((countyIdx = address.indexOf("市")) > -1) {
idx[3] = countyIdx;
}
if ((countyIdx = address.indexOf("區(qū)")) > -1) {
idx[4] = countyIdx;
}
if ((countyIdx = address.indexOf("島")) > -1) {
idx[5] = countyIdx;
}
Arrays.sort(idx);
for (int j : idx) {
if (j > 0) {
return j;
}
}
return countyIdx;
}
/**
* 身份證地址提取省市區(qū)
*
* @param fullAddress 身份證完整地址
*/
public static Map<String, String> addressResolution(String fullAddress) {
// 定義正則
String regex = "(?<province>[^省]+自治區(qū)|.*?省|.*?行政區(qū)|.*?市)(?<city>[^市]+自治州|.*?地區(qū)|.*?行政單位|.+盟|市轄區(qū)|.*?市|.*?縣)(?<area>[^縣]+縣|.+區(qū)|.+市|.+旗|.+海域|.+島)?(?<town>[^區(qū)]+區(qū)|.+鎮(zhèn))?(?<detail>.*)";
Matcher matcher = Pattern.compile(regex).matcher(fullAddress);
String province, city, area, town, detail;
Map<String, String> map = new LinkedHashMap<>();
while (matcher.find()) {
province = matcher.group("province");
map.put("province", StringUtils.isEmpty(province) ? "" : province.trim());
city = matcher.group("city");
map.put("city", StringUtils.isEmpty(city) ? "" : city.trim());
area = matcher.group("area");
map.put("area", StringUtils.isEmpty(area) ? "" : area.trim());
town = matcher.group("town");
map.put("town", StringUtils.isEmpty(town) ? "" : town.trim());
detail = matcher.group("detail");
map.put("detail", StringUtils.isEmpty(detail) ? "" : detail.trim());
}
return map;
}
public static void main(String[] args) {
String address1 = "上海市上海市浦東新區(qū)世紀(jì)大道xx號(hào)上海中心大廈xx樓A座";
String address2 = "內(nèi)蒙古自治區(qū)呼倫貝爾市鄂溫克族自治旗額爾古納市阿爾山北路xxx號(hào)蒙古民族文化博物館x樓xx展廳";
String address3 = "廣東省廣州市番禺區(qū)沙灣鎮(zhèn)大巷涌路xxx號(hào)";
System.out.println("詳細(xì)地址1:" + getDetailedAddress(address1));
System.out.println("詳細(xì)地址2:" + getDetailedAddress(address2));
System.out.println("省市區(qū)地址拼接1:" + getPcaAddress(address1));
System.out.println("省市區(qū)地址拼接2:" + getPcaAddress(address2));
System.out.println("地址數(shù)組1:" + Arrays.toString(spliceDetailedAddress(address1)));
System.out.println("地址數(shù)組2:" + Arrays.toString(spliceDetailedAddress(address2)));
System.out.println("地址提取省市區(qū):" + addressResolution(address2));
System.out.println("地址提取省市區(qū):" + addressResolution(address3));
}
}測試結(jié)果:

到此這篇關(guān)于Java實(shí)現(xiàn)根據(jù)地址智能識(shí)別省市區(qū)縣的文章就介紹到這了,更多相關(guān)Java地址識(shí)別省市區(qū)縣內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
IDEA項(xiàng)目代碼上傳gitlab遠(yuǎn)程倉庫過程圖解
這篇文章主要介紹了IDEA項(xiàng)目代碼上傳gitlab遠(yuǎn)程倉庫過程圖解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-09-09
StringUtils,CollectionUtils判斷為空的方法和原生代碼哪個(gè)效率最高
這篇文章主要介紹了StringUtils,CollectionUtils判斷為空的方法和原生代碼哪個(gè)效率最高,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-02-02
深入了解Java數(shù)據(jù)結(jié)構(gòu)和算法之堆
這篇文章主要為大家介紹了Java數(shù)據(jù)結(jié)構(gòu)和算法之堆 ,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-01-01
部署在linux上的java服務(wù)老是掛掉問題排查日志
當(dāng)服務(wù)器掛掉時(shí),操作系統(tǒng)通常會(huì)記錄一些異常信息,檢查服務(wù)器的系統(tǒng)日志可以幫助定位問題所在,這篇文章主要介紹了部署在linux上的java服務(wù)老是掛掉問題排查日志的相關(guān)資料,需要的朋友可以參考下2025-10-10
Java中ArrayList與順序表的定義與實(shí)現(xiàn)方法
ArrayList是一個(gè)實(shí)現(xiàn)List接口的類,底層是動(dòng)態(tài)類型順序表,本質(zhì)也就是數(shù)組,動(dòng)態(tài)主要體現(xiàn)在它的擴(kuò)容機(jī)制,下面這篇文章主要給大家介紹了關(guān)于Java中ArrayList與順序表的定義與實(shí)現(xiàn)的相關(guān)資料,需要的朋友可以參考下2022-07-07

