从字符串中提取符合规则的汽车车牌

复制代码
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Component
public class LicensePlateExtractorUtil {
    // 蓝牌正则:省份简称(1汉字) + 发牌机关代号(1字母) + 5位序号(字母/数字)
    // 排除I和O避免与1和0混淆
    private static final String BLUE_PLATE_REGEX = "[\\u4e00-\\u9fa5][A-Z][A-HJ-NP-Z0-9]{5}";

    // 新能源车牌正则:
    // 小型车:省份简称(1汉字) + 发牌机关代号(1字母,D/F) + 6位序号(前4位数字+后1位字母)
    // 大型车:省份简称(1汉字) + 发牌机关代号(1字母) + 6位序号(前1位字母+后5位数字)
    private static final String NEW_ENERGY_PLATE_REGEX = "[\\u4e00-\\u9fa5][A-Z][A-HJ-NP-Z0-9]{6}";

    // 使馆车牌正则 (特殊车牌示例)
    private static final String EMBASSY_PATTERN = "使[A-Z0-9]{6}";

    // 武警车牌正则 (特殊车牌示例)
    private static final String MILITARY_PATTERN = "WJ[\\u4e00-\\u9fa5]{0,1}[0-9]{5}";

    // 合并正则
    private static final String COMBINED_REGEX =  NEW_ENERGY_PLATE_REGEX + "|" + BLUE_PLATE_REGEX + "|" + EMBASSY_PATTERN + "|" + MILITARY_PATTERN;

    // 预编译正则
    private static final Pattern PLATE_PATTERN = Pattern.compile(COMBINED_REGEX);

    // 中国省级行政区简称集合(包括省、自治区、直辖市、特别行政区)
    private static final Set<String> VALID_PROVINCE_CODES;

    static {
        // 初始化有效省份简称集合
        VALID_PROVINCE_CODES = new HashSet<>();
        // 直辖市
        VALID_PROVINCE_CODES.add("京"); // 北京
        VALID_PROVINCE_CODES.add("津"); // 天津
        VALID_PROVINCE_CODES.add("沪"); // 上海
        VALID_PROVINCE_CODES.add("渝"); // 重庆
        // 省
        VALID_PROVINCE_CODES.add("冀"); // 河北
        VALID_PROVINCE_CODES.add("晋"); // 山西
        VALID_PROVINCE_CODES.add("辽"); // 辽宁
        VALID_PROVINCE_CODES.add("吉"); // 吉林
        VALID_PROVINCE_CODES.add("黑"); // 黑龙江
        VALID_PROVINCE_CODES.add("苏"); // 江苏
        VALID_PROVINCE_CODES.add("浙"); // 浙江
        VALID_PROVINCE_CODES.add("皖"); // 安徽
        VALID_PROVINCE_CODES.add("闽"); // 福建
        VALID_PROVINCE_CODES.add("赣"); // 江西
        VALID_PROVINCE_CODES.add("鲁"); // 山东
        VALID_PROVINCE_CODES.add("豫"); // 河南
        VALID_PROVINCE_CODES.add("鄂"); // 湖北
        VALID_PROVINCE_CODES.add("湘"); // 湖南
        VALID_PROVINCE_CODES.add("粤"); // 广东
        VALID_PROVINCE_CODES.add("琼"); // 海南
        VALID_PROVINCE_CODES.add("川"); // 四川
        VALID_PROVINCE_CODES.add("贵"); // 贵州
        VALID_PROVINCE_CODES.add("云"); // 云南
        VALID_PROVINCE_CODES.add("陕"); // 陕西
        VALID_PROVINCE_CODES.add("甘"); // 甘肃
        VALID_PROVINCE_CODES.add("青"); // 青海
        VALID_PROVINCE_CODES.add("台"); // 台湾
        // 自治区
        VALID_PROVINCE_CODES.add("蒙"); // 内蒙古
        VALID_PROVINCE_CODES.add("桂"); // 广西
        VALID_PROVINCE_CODES.add("宁"); // 宁夏
        VALID_PROVINCE_CODES.add("新"); // 新疆
        VALID_PROVINCE_CODES.add("藏"); // 西藏
        // 特别行政区
        VALID_PROVINCE_CODES.add("港"); // 香港
        VALID_PROVINCE_CODES.add("澳"); // 澳门
    }

    /**
     * 从字符串中提取所有蓝牌和新能源车牌
     * @param input 待提取的字符串
     * @return 提取到的车牌列表,无匹配时返回空列表
     */
    public static List<String> extractAllPlates(String input) {
        List<String> plates = new ArrayList<>();
        if (input == null || input.isEmpty()) {
            return plates;
        }

        Matcher matcher = PLATE_PATTERN.matcher(input);
        while (matcher.find()) {
            String group = matcher.group();

            String provinceCode = group.substring(0, 1);
            if (StringUtils.equals(provinceCode,"使") || StringUtils.equals(provinceCode,"W")){

            }else {
                boolean validProvinceCode = isValidProvinceCode(provinceCode);
                if (!validProvinceCode){
                    continue;
                }
            }

            plates.add(group);
        }
        return plates;
    }

    /**
     * 区分蓝牌和新能源车牌
     * @param plate 车牌号码
     * @return 车牌类型描述
     */
    public static String getPlateType(String plate) {
        if (plate == null) {
            return "无效车牌";
        }
        if (plate.matches(BLUE_PLATE_REGEX)) {
            return "蓝牌";
        } else if (plate.matches(NEW_ENERGY_PLATE_REGEX)) {
            return "新能源车牌";
        }  else if (plate.matches(EMBASSY_PATTERN)) {
            return "使馆车牌";
        }  else if (plate.matches(MILITARY_PATTERN)) {
            return "武警车牌";
        } else {
            return "无效车牌";
        }
    }

    /**
     * 校验省份简称是否有效
     * @param code 省份简称(单个汉字)
     * @return true-有效,false-无效
     */
    public static boolean isValidProvinceCode(String code) {
        // 校验输入是否为单个汉字
        if (code == null || code.length() != 1) {
            return false;
        }
        // 校验是否在有效集合中
        return VALID_PROVINCE_CODES.contains(code);
    }

    public static void main(String[] args) {
        String testStr = "停车场内有:京A12345(蓝牌)、粤AD12345(新能源)、沪B67890(蓝牌)、苏AF67890(新能源)、无效车牌ABC123、使123456、WJ123456、冀X12345";

        // 提取车牌
        List<String> plates = extractAllPlates(testStr);
        System.out.println("提取到的车牌:" + JSONObject.toJSONString(plates));
        for (String plate : plates) {
            System.out.println(plate + "|" + getPlateType(plate));
        }
    }
}

代码执行结果:

提取到的车牌:["京A12345","粤AD12345","沪B67890","苏AF67890","使123456","WJ12345","冀X12345"]

京A12345|蓝牌

粤AD12345|新能源车牌

沪B67890|蓝牌

苏AF67890|新能源车牌

使123456|使馆车牌

WJ12345|武警车牌

冀X12345|蓝牌

相关推荐
喵手8 分钟前
如何利用Java的Stream API提高代码的简洁度和效率?
java·后端·java ee
-Xie-9 分钟前
Maven(二)
java·开发语言·maven
IT利刃出鞘22 分钟前
Java线程的6种状态和JVM状态打印
java·开发语言·jvm
天天摸鱼的java工程师1 小时前
Java 解析 JSON 文件:八年老开发的实战总结(从业务到代码)
java·后端·面试
白仑色1 小时前
Spring Boot 全局异常处理
java·spring boot·后端·全局异常处理·统一返回格式
喵手1 小时前
反射机制:你真的了解它的“能力”吗?
java·后端·java ee
kaika12 小时前
告别复杂配置!使用 1Panel 运行环境功能轻松搭建 Java 应用
java·1panel·建站·halo
有梦想的攻城狮2 小时前
Java 11中的Collections类详解
java·windows·python·java11·collections
33255_40857_280592 小时前
从韩立结婴看Java进阶:一个10年老码农的修仙式成长指南
java