import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.regex.Pattern;
/**
* 車牌號校驗工具類
*/
public class LicensePlateValidator {
// 全國省級行政區簡稱集合
private static final Set<String> PROVINCE_CODES = new HashSet<>(Arrays.asList(
"京", "津", "滬", "渝", "冀", "晉", "遼", "吉", "黑", "蘇", "浙", "皖", "閩", "贛", "魯",
"豫", "鄂", "湘", "粵", "瓊", "川", "貴", "雲", "陝", "甘", "青", "寧", "新", "蒙", "桂",
"藏", "港", "澳", "台"
));
// 普通燃油車正則:省份簡稱+字母+5位序號
private static final Pattern NORMAL_PLATE_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}$");
// 小型新能源正則:省份簡稱+字母+D/F+5位序號
private static final Pattern NEW_ENERGY_SMALL_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5][A-Z][DF][A-Z0-9]{5}$");
// 大型新能源正則:省份簡稱+字母+5位序號+D/F
private static final Pattern NEW_ENERGY_LARGE_PATTERN = Pattern.compile("^[\\u4e00-\\u9fa5][A-Z][A-Z0-9]{5}[DF]$");
/**
* 校驗車牌號是否合法
* @param licensePlate 車牌號(支持大小寫字母)
* @return 合法返回true,否則false
*/
public static boolean isValidLicensePlate(String licensePlate) {
// 1. 空值/長度校驗
if (licensePlate == null || licensePlate.trim().isEmpty()) {
return false;
}
String plate = licensePlate.trim().toUpperCase(); // 統一轉大寫
int length = plate.length();
if (length != 7 && length != 8) { // 普通7位,新能源8位
return false;
}
// 2. 省份簡稱校驗(第一個字符必須是合法簡稱)
String provinceCode = plate.substring(0, 1);
if (!PROVINCE_CODES.contains(provinceCode)) {
return false;
}
// 3. 正則匹配
return NORMAL_PLATE_PATTERN.matcher(plate).matches()
|| NEW_ENERGY_SMALL_PATTERN.matcher(plate).matches()
|| NEW_ENERGY_LARGE_PATTERN.matcher(plate).matches();
}
// 測試用例
public static void main(String[] args) {
String[] testPlates = {
"京A12345", // 普通燃油車(合法)
"滬B6789C", // 普通燃油車(合法)
"粵AD12345", // 小型新能源(合法)
"蘇A12345F", // 大型新能源(合法)
"XYZ12345", // 無省份簡稱(非法)
"京A1234", // 長度不足(非法)
"京A1234567", // 長度過長(非法)
"京G12345D", // 大型新能源(合法)
"港A12345", // 港澳入境車(合法)
"京a12345" // 小寫字母(合法,會轉大寫)
};
for (String plate : testPlates) {
System.out.printf("車牌號:%s → %s%n", plate, isValidLicensePlate(plate) ? "合法" : "非法");
}
}
}