首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 從字符串提取數字的四種高效方法:正則、ASCII、Character API 與手動解析

     編輯:Java 相關知識

場景與需求

從混合字符串(如 "abc123def456"、"訂單號:20230901")中提取連續數字子串,是日誌解析、數據清洗、表單驗證的高頻需求。本文匯總四種主流實現,附性能與適用場景分析。

方法一:Character.isDigit() 手動遍歷(最靈活)

public static List<String> extractNumbers(String input) {
    List<String> result = new ArrayList<>();
    int start = -1;
    for (int i = 0; i < input.length(); i++) {
        char c = input.charAt(i);
        if (Character.isDigit(c)) {
            if (start == -1) start = i; // 數字序列開始
        } else {
            if (start != -1) {          // 數字序列結束
                result.add(input.substring(start, i));
                start = -1;
            }
        }
    }
    // 處理以數字結尾的情況
    if (start != -1) result.add(input.substring(start));
    return result;
}

優點:無依賴、可精確控制提取邏輯(如排除負號、小數點)、支持補充非 ASCII 數字(全角數字等);
缺點:代碼較長、需自行處理邊界。

方法二:正則表達式(最簡潔)

public static List<String> extractNumbersRegex(String input) {
    Pattern pattern = Pattern.compile("\\d+"); // 連續數字
    Matcher matcher = pattern.matcher(input);
    List<String> result = new ArrayList<>();
    while (matcher.find()) {
        result.add(matcher.group());
    }
    return result;
}

// 一行流式寫法 (Java 9+)
public static List<String> extractNumbersStream(String input) {
    return Pattern.compile("\\d+").matcher(input).results()
        .map(MatchResult::group).collect(Collectors.toList());
}

優點:代碼極少、可讀性強、易擴展(如 -?\\d+(\\.\\d+)? 提取負數/小數);
缺點:編譯 Pattern 有開銷(高頻調用建議靜態編譯緩存)、極長字符串可能回溯慢。

方法三:ASCII 碼範圍判斷(最原始、性能基準)

public static List<String> extractNumbersAscii(String input) {
    List<String> result = new ArrayList<>();
    int start = -1;
    for (int i = 0; i < input.length(); i++) {
        char c = input.charAt(i);
        if (c >= '0' && c <= '9') { // ASCII 48-57
            if (start == -1) start = i;
        } else {
            if (start != -1) {
                result.add(input.substring(start, i));
                start = -1;
            }
        }
    }
    if (start != -1) result.add(input.substring(start));
    return result;
}

優點:無方法調用開銷、JIT 易優化、性能通常最優;
缺點:僅支持 ASCII 數字、可讀性稍差、硬編碼魔數。

方法四:Java 內置工具方法(原文片段,有缺陷)


// 原文片段:僅判斷「整串是否全為數字」,非提取
public static boolean isNumeric(String str) {
    for (int i = str.length(); --i >= 0;) {
        if (!Character.isDigit(str.charAt(i))) return false;
    }
    return true;
}

注意:此方法不能提取子串,只能驗證純數字字符串。若需提取,請用方法 1-3。

性能基準測試(JMH 參考)

方法吞吐量適用場景
ASCII 手動遍歷最高極高頻、極長文本、嵌入式/Android 早期版本
Character.isDigit 遍歷高(接近 ASCII)通用業務、需支持 Unicode 數字
正則 Pattern 復用中高業務邏輯複雜、需提取多種模式、代碼可讀性優先
正則臨時編譯低一次性腳本、低頻調用

實戰建議

  1. 通用業務:靜態編譯 Pattern NUMBER_PATTERN = Pattern.compile("\\d+"),復用 Matcher;
  2. 高性能場景:手寫 ASCII/Character 遍歷,避免對象創建;
  3. 複雜提取:正則擴展(如 -?\\d+(\\.\\d+)? 提取浮點數、0x[0-9a-fA-F]+ 提取十六進制);
  4. Android 早期版本:避免正則,用遍歷法規避 Dalvik 正則性能短板。

完整工具類

public final class NumberExtractor {
    private static final Pattern DIGITS = Pattern.compile("\\d+");
    
    private NumberExtractor() {}

    /** 提取所有連續數字子串(推薦通用) */
    public static List<String> extractAll(String input) {
        if (input == null || input.isEmpty()) return Collections.emptyList();
        Matcher m = DIGITS.matcher(input);
        List<String> res = new ArrayList<>();
        while (m.find()) res.add(m.group());
        return res;
    }

    /** 提取第一個數字子串 */
    public static String extractFirst(String input) {
        if (input == null) return null;
        Matcher m = DIGITS.matcher(input);
        return m.find() ? m.group() : null;
    }

    /** 提取最後一個數字子串 */
    public static String extractLast(String input) {
        if (input == null) return null;
        Matcher m = DIGITS.matcher(input);
        String last = null;
        while (m.find()) last = m.group();
        return last;
    }

    /** 判斷純數字字符串 */
    public static boolean isNumeric(String str) {
        return str != null && DIGITS.matcher(str).matches(); // ^\\d+$
    }
}

總結

提取數字子串,正則表達式(靜態編譯復用)是首選,兼顧可讀性與性能;極致性能場景手寫 Character.isDigit() 或 ASCII 遍歷;切記區分「提取子串」與「驗證純數字」兩類不同需求,選對工具事半功倍。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved