|
|
@@ -25,6 +25,11 @@ public class TruckNoUtils {
|
|
|
*/
|
|
|
private static final String TRUCK_NO_PATTERN_8 = "^[京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使]{1}[A-Z]{1}[0-9A-Z]{6}$";
|
|
|
|
|
|
+ /**
|
|
|
+ * 省份简称(用于智能拆分车牌号)
|
|
|
+ */
|
|
|
+ private static final String PROVINCES = "京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使";
|
|
|
+
|
|
|
/**
|
|
|
* 支持的分隔符:中文逗号、英文逗号、空格、换行符、制表符
|
|
|
*/
|
|
|
@@ -79,9 +84,11 @@ public class TruckNoUtils {
|
|
|
|
|
|
/**
|
|
|
* 从字符串中拆分车牌号
|
|
|
- * 支持中文逗号、英文逗号、空格、换行符等分隔符
|
|
|
+ * 支持两种模式:
|
|
|
+ * 1. 分隔符模式:中文逗号、英文逗号、空格、换行符等分隔符
|
|
|
+ * 2. 智能识别模式:无分隔符,通过识别省份简称自动拆分(如:川A12345京B67890)
|
|
|
*
|
|
|
- * @param truckNoStr 车牌号字符串,如:"川A12345,京B67890,粤C11111 沪D22222"
|
|
|
+ * @param truckNoStr 车牌号字符串,如:"川A12345,京B67890" 或 "川A12345京B67890"
|
|
|
* @return 车牌号列表
|
|
|
*/
|
|
|
public static List<String> splitTruckNos(String truckNoStr) {
|
|
|
@@ -89,17 +96,103 @@ public class TruckNoUtils {
|
|
|
return new ArrayList<>();
|
|
|
}
|
|
|
|
|
|
- // 使用正则表达式分割
|
|
|
+ List<String> result = new ArrayList<>();
|
|
|
+
|
|
|
+ // 先尝试按分隔符拆分
|
|
|
String[] parts = truckNoStr.split(DELIMITER_PATTERN);
|
|
|
|
|
|
- return Arrays.stream(parts)
|
|
|
- .map(String::trim)
|
|
|
+ for (String part : parts) {
|
|
|
+ if (StringUtils.isBlank(part)) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 去除空格并转大写
|
|
|
+ String cleaned = part.trim().replaceAll("\\s+", "").toUpperCase();
|
|
|
+
|
|
|
+ // 检查是否包含多个车牌号(通过识别省份简称)
|
|
|
+ List<String> subParts = splitByProvince(cleaned);
|
|
|
+ result.addAll(subParts);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result.stream()
|
|
|
.filter(StringUtils::isNotBlank)
|
|
|
- .map(TruckNoUtils::formatTruckNo)
|
|
|
.distinct()
|
|
|
.collect(Collectors.toList());
|
|
|
}
|
|
|
|
|
|
+ /**
|
|
|
+ * 通过识别省份简称智能拆分车牌号
|
|
|
+ * 例如:"川A12345京B67890" -> ["川A12345", "京B67890"]
|
|
|
+ *
|
|
|
+ * @param str 待拆分的字符串
|
|
|
+ * @return 拆分后的车牌号列表
|
|
|
+ */
|
|
|
+ private static List<String> splitByProvince(String str) {
|
|
|
+ List<String> result = new ArrayList<>();
|
|
|
+
|
|
|
+ if (StringUtils.isBlank(str)) {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ int i = 0;
|
|
|
+ while (i < str.length()) {
|
|
|
+ char c = str.charAt(i);
|
|
|
+
|
|
|
+ // 检查是否为省份简称
|
|
|
+ if (PROVINCES.indexOf(c) != -1) {
|
|
|
+ // 找到省份简称,尝试提取完整车牌号
|
|
|
+ String truckNo = extractTruckNo(str, i);
|
|
|
+ if (StringUtils.isNotBlank(truckNo)) {
|
|
|
+ result.add(truckNo);
|
|
|
+ i += truckNo.length();
|
|
|
+ } else {
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ i++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果没有识别到省份简称,说明可能是完整的单个车牌号
|
|
|
+ if (result.isEmpty() && StringUtils.isNotBlank(str)) {
|
|
|
+ result.add(str);
|
|
|
+ }
|
|
|
+
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从指定位置提取车牌号
|
|
|
+ * 车牌号格式:省份简称(1位) + 字母(1位) + 数字/字母(5-6位)
|
|
|
+ *
|
|
|
+ * @param str 源字符串
|
|
|
+ * @param startIndex 起始位置(省份简称的位置)
|
|
|
+ * @return 提取的车牌号,如果格式不正确返回空字符串
|
|
|
+ */
|
|
|
+ private static String extractTruckNo(String str, int startIndex) {
|
|
|
+ // 最短7位(标准车牌),最长8位(新能源车牌)
|
|
|
+ int minLength = 7;
|
|
|
+ int maxLength = 8;
|
|
|
+
|
|
|
+ // 先尝试提取8位(新能源车牌)
|
|
|
+ if (startIndex + maxLength <= str.length()) {
|
|
|
+ String candidate = str.substring(startIndex, startIndex + maxLength);
|
|
|
+ if (isValidTruckNo(candidate)) {
|
|
|
+ return candidate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 再尝试提取7位(标准车牌)
|
|
|
+ if (startIndex + minLength <= str.length()) {
|
|
|
+ String candidate = str.substring(startIndex, startIndex + minLength);
|
|
|
+ if (isValidTruckNo(candidate)) {
|
|
|
+ return candidate;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return "";
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 获取车牌号校验失败的原因
|
|
|
*
|
|
|
@@ -124,8 +217,7 @@ public class TruckNoUtils {
|
|
|
|
|
|
// 检查省份简称
|
|
|
char province = formatted.charAt(0);
|
|
|
- String provinces = "京津冀晋蒙辽吉黑沪苏浙皖闽赣鲁豫鄂湘粤桂琼川贵云渝藏陕甘青宁新使";
|
|
|
- if (provinces.indexOf(province) == -1) {
|
|
|
+ if (PROVINCES.indexOf(province) == -1) {
|
|
|
return "省份简称不正确:" + province;
|
|
|
}
|
|
|
|