簡體   English   中英

如何檢查字符串代表的數字和數字類型?

[英]How to check if and what type of number a string represents?

如何檢查字符串是表示長,雙,還是只是常規字符串? 我需要這樣做,因為這個值需要根據其類型在數據庫中建立索引。 目前我這樣做是通過嘗試解析字符串並檢查異常但由於代碼被頻繁調用,我想知道是否有更有效的方法來執行它。 我的代碼目前看起來像這樣:

String value = ...;
// For example, could be "213678", "654.1236781", or "qwerty12345"

try {
    Long longValue = Long.parseLong(value);
    // Index 'longValue' in the database
} catch (NumberFormatException parseLongException) {
    try {
        Double doubleValue = Double.parseDouble(value);
        // Index 'doubleValue' in the database
    } catch (NumberFormatException parseDoubleException) {
        // Index 'value' in the database
    }
}

編輯:

我只是根據@ user949300建議使用正則表達式模式進行了快速基准測試,它的表現略好於上面的異常處理代碼。 這是代碼,以防其他人發現它有用:

Pattern longPattern = Pattern.compile("^[-+]?[0-9]+$");
Pattern doublePattern = Pattern.compile("^[-+]?[0-9]*\\.?[0-9]+([eE][-+]?[0-9]+)?$");

// Check for long regex pattern before the double regex pattern
// since the former is a strict subset of the latter
if (longPattern.matcher(value).matches()) {
    // Perform indexing for long in the database
} else if (doublePattern.matcher(value).matches()) {
    // Perform indexing for double in the database
} else {
    // Perform indexing for string in the database
}

以下是檢查50,000個條目的基准測試結果,其中類型的近似細分為50%長度,10%雙倍,40%字符串(代表我的應用程序處理的工作負載):

--- Exception handling code ---
STRING - actual: 19861, found: 19861
DOUBLE - actual: 4942, found: 4942
LONG - actual: 25197, found: 25197
Time taken: 2561 ms

--- Regex pattern matching code ---
STRING - actual: 19861, found: 19861
DOUBLE - actual: 4942, found: 4942
LONG - actual: 25197, found: 25197
Time taken: 1565 ms

你考慮過正則表達式嗎?

如果String包含除 - (在開頭)和0-9或。之外的任何內容,則它是一個String。 (注意 - 這忽略了國際化和科學記數法 - 它們是否有問題?)

否則,它包含一個。,它是一個雙。 (好吧,你應該只測試一個。,但這是一個開始)

否則,這是一個漫長的過程。

出於偏執,我仍然可以檢查例外,但這可能是一種更快的方式。

注意添加我猜測測試正則表達式比從各種解析例程中拋出異常要快,但實際上這可能不是真的。 你應該做一些測試。

據我所知,除此之外沒有其他優雅的方法可以做到這一點。 我建議你按照最常見和最不常見的順序解析它們,以便盡可能快地完成。

如果你有超過3種可能的類型,那么你將擁有一個深度和丑陋的try-catch嵌套,但從技術上講,它會比你將每個解析嘗試分解為自己的方法更快; 這里的權衡是你是想要代碼清晰還是更快的執行 - 聽起來你可能想要后者。

您可以通過檢查非數字以檢測長時間來獲得一些改進(特別是如果您可以排除科學記數法,例如1e12 )。

Long.parseLong()委托一個在任何數字基礎上工作的通用方法,因此只有十進制的方法可能會快一點。

不要忘記減號,如果您的數據中有可能......

雙打更難,因為654.1236871有效,但654.12.36.87...1不是,盡管它們包含相同的字符集。 因此可能需要完全解析。

你的代碼看起來不錯。

做一些分析,如果基於它你發現你的代碼太慢,那么你可以考慮潛在的優化(比如簡單的循環來查看所有字符是否都是數字)。

在分析之前不要嘗試優化代碼。 尤其是像java這樣的語言。

一種可能是java.io.StreamTokenizer:

Reader r = new StringReader(value);
StreamTokenizer st = new StreamTokenizer(r);
int tokenType = st.nextToken();
double number;
String word;
switch (tokenType) {
    case StreamTokenizer.TT_NUMBER: // it's a number
         number = st.nval; break;
    case StreamTokenizer.TT_WORD: // it's a string
         word = st.sval; break;
}

雖然使用它可能有點棘手。

如果你不需要擔心你的Longs是否定的,你可以使用Apache Commons Lang庫中的NumberUtils.isDigits()NumberUtils.isNumber()

if(NumberUtils.isDidgets(string)){
    //Index long
} else if(NumberUtils.isNumber(string)){
    //Index double
} else {
    //Index string
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM