Как проверить, является ли строка числовой в Java


Как бы вы проверили, была ли строка числом, прежде чем разбирать ее?

30 719

30 ответов:

С Apache Commons Lang 3.5 и выше: NumberUtils.isCreatable или StringUtils.isNumeric.

С Apache Commons Lang 3.4 и ниже: NumberUtils.isNumber или StringUtils.isNumeric.

вы также можете использовать StringUtils.isNumericSpace возвращает true для пустых строк и игнорирует внутренние пробелы в строке. (Связанной документации содержит подробные примеры для каждого метода.)

как правило, это делается с помощью простой пользовательской функции (т. е. Roll-your-own "isNumeric" функция).

что-то типа:

public static boolean isNumeric(String str)  
{  
  try  
  {  
    double d = Double.parseDouble(str);  
  }  
  catch(NumberFormatException nfe)  
  {  
    return false;  
  }  
  return true;  
}

однако, если вы вызываете эту функцию много, и вы ожидаете, что многие из проверок потерпят неудачу из-за того, что не являются числом, то производительность этого механизма не будет большой, так как вы полагаетесь на исключения, создаваемые для каждого сбоя, что является довольно дорогостоящей операцией.

альтернативный подход может быть чтобы использовать регулярное выражение для проверки правильности числа:

public static boolean isNumeric(String str)
{
  return str.matches("-?\d+(\.\d+)?");  //match a number with optional '-' and decimal.
}

будьте осторожны с вышеуказанным механизмом регулярных выражений, хотя, как это не удастся, если вы используете неарабские цифры (т. е. цифры, отличные от 0 до 9). Это связано с тем, что часть" \d " регулярного выражения будет соответствовать только [0-9] и фактически не имеет международного числового представления. (Спасибо OregonGhost за указание на это!)

или даже другой альтернативой является использование встроенного Java Ява.текст.NumberFormat объект, чтобы увидеть, если после разбора строки позиция синтаксического анализатора находится в конце строки. Если это так, мы можем предположить, что вся строка числовая:

public static boolean isNumeric(String str)
{
  NumberFormat formatter = NumberFormat.getInstance();
  ParsePosition pos = new ParsePosition(0);
  formatter.parse(str, pos);
  return str.length() == pos.getIndex();
}

Если вы находитесь на Android, то вы должны использовать:

android.text.TextUtils.isDigitsOnly(CharSequence str)

документация может быть найдена здесь

сохранить его простым. в основном все могут "перепрограммировать" (то же самое).

как упоминал @CraigTP в своем превосходном ответе, у меня также есть аналогичные проблемы с производительностью при использовании исключений для проверки того, является ли строка числовой или нет. Поэтому я в конечном итоге разделяю строку и использую java.lang.Character.isDigit().

public static boolean isNumeric(String str)
{
    for (char c : str.toCharArray())
    {
        if (!Character.isDigit(c)) return false;
    }
    return true;
}

по данным Javadoc,Character.isDigit(char) корректно распознает латинские цифры. С точки зрения производительности, я думаю, что простое число n сравнений, Где N-количество символов в строке, будет более вычислительно эффективным, чем выполнение сопоставления регулярных выражений.

UPDATE: как указал Жан-Франсуа Корбетт в комментарии, приведенный выше код будет проверять только положительные целые числа, которые охватывают большую часть моего варианта использования. Ниже приведен обновленный код, который правильно проверяет десятичные числа в соответствии с языковым стандартом по умолчанию, используемым в вашей системе, с предположением, что десятичный разделитель встречается только один раз в строке.

public static boolean isStringNumeric( String str )
{
    DecimalFormatSymbols currentLocaleSymbols = DecimalFormatSymbols.getInstance();
    char localeMinusSign = currentLocaleSymbols.getMinusSign();

    if ( !Character.isDigit( str.charAt( 0 ) ) && str.charAt( 0 ) != localeMinusSign ) return false;

    boolean isDecimalSeparatorFound = false;
    char localeDecimalSeparator = currentLocaleSymbols.getDecimalSeparator();

    for ( char c : str.substring( 1 ).toCharArray() )
    {
        if ( !Character.isDigit( c ) )
        {
            if ( c == localeDecimalSeparator && !isDecimalSeparatorFound )
            {
                isDecimalSeparatorFound = true;
                continue;
            }
            return false;
        }
    }
    return true;
}

Java 8 лямбда-выражения.

String someString = "123123";
boolean isNumeric = someString.chars().allMatch( Character::isDigit );

библиотека гуавы Google предоставляет хороший вспомогательный метод для этого:Ints.tryParse. Вы используете его как Integer.parseInt но он возвращает null вместо того, чтобы выдавать исключение, если строка не разбирается на допустимое целое число. Обратите внимание, что он возвращает Integer, а не int, поэтому вам нужно преобразовать/autobox обратно в int.

пример:

String s1 = "22";
String s2 = "22.2";
Integer oInt1 = Ints.tryParse(s1);
Integer oInt2 = Ints.tryParse(s2);

int i1 = -1;
if (oInt1 != null) {
    i1 = oInt1.intValue();
}
int i2 = -1;
if (oInt2 != null) {
    i2 = oInt2.intValue();
}

System.out.println(i1);  // prints 22
System.out.println(i2);  // prints -1

однако, по состоянию на текущий релиз -- Guava r11 -- он по-прежнему помечен @Beta.

Я не сравнивал его. Глядя на источник код есть некоторые накладные расходы от проверки работоспособности, но в конце концов они использовать Character.digit(string.charAt(idx)), похоже, но немного отличается от ответа от @Ibrahim выше. В их реализации нет накладных расходов на обработку исключений под крышками.

не используйте исключения для проверки ваших ценностей. Используйте util libs вместо этого, как apache NumberUtils:

NumberUtils.isNumber(myStringValue);

Edit:

NumberUtils.isNumber("07") //true
NumberUtils.isNumber("08") //false

почему все настаивают на исключениях / регулярных выражениях?

хотя я могу понять, что большинство людей в порядке с использованием try / catch, если вы хотите делать это часто... это может быть очень трудно.

то, что я сделал здесь, было взять регулярное выражение, методы parseNumber() и метод поиска массива, чтобы увидеть, какой из них был наиболее эффективным. На этот раз я смотрел только на целые числа.

public static boolean isNumericRegex(String str) {
    if (str == null)
        return false;
    return str.matches("-?\d+");
}

public static boolean isNumericArray(String str) {
    if (str == null)
        return false;
    char[] data = str.toCharArray();
    if (data.length <= 0)
        return false;
    int index = 0;
    if (data[0] == '-' && data.length > 1)
        index = 1;
    for (; index < data.length; index++) {
        if (data[index] < '0' || data[index] > '9') // Character.isDigit() can go here too.
            return false;
    }
    return true;
}

public static boolean isNumericException(String str) {
    if (str == null)
        return false;
    try {  
        /* int i = */ Integer.parseInt(str);
    } catch (NumberFormatException nfe) {  
        return false;  
    }
    return true;
}

результаты в скорости я получил были:

Done with: for (int i = 0; i < 10000000; i++)...

With only valid numbers ("59815833" and "-59815833"):
    Array numeric took 395.808192 ms [39.5808192 ns each]
    Regex took 2609.262595 ms [260.9262595 ns each]
    Exception numeric took 428.050207 ms [42.8050207 ns each]
    // Negative sign
    Array numeric took 355.788273 ms [35.5788273 ns each]
    Regex took 2746.278466 ms [274.6278466 ns each]
    Exception numeric took 518.989902 ms [51.8989902 ns each]
    // Single value ("1")
    Array numeric took 317.861267 ms [31.7861267 ns each]
    Regex took 2505.313201 ms [250.5313201 ns each]
    Exception numeric took 239.956955 ms [23.9956955 ns each]
    // With Character.isDigit()
    Array numeric took 400.734616 ms [40.0734616 ns each]
    Regex took 2663.052417 ms [266.3052417 ns each]
    Exception numeric took 401.235906 ms [40.1235906 ns each]

With invalid characters ("5981a5833" and "a"):
    Array numeric took 343.205793 ms [34.3205793 ns each]
    Regex took 2608.739933 ms [260.8739933 ns each]
    Exception numeric took 7317.201775 ms [731.7201775 ns each]
    // With a single character ("a")
    Array numeric took 291.695519 ms [29.1695519 ns each]
    Regex took 2287.25378 ms [228.725378 ns each]
    Exception numeric took 7095.969481 ms [709.5969481 ns each]

With null:
    Array numeric took 214.663834 ms [21.4663834 ns each]
    Regex took 201.395992 ms [20.1395992 ns each]
    Exception numeric took 233.049327 ms [23.3049327 ns each]
    Exception numeric took 6603.669427 ms [660.3669427 ns each] if there is no if/null check

отказ от ответственности: я не утверждаю, что эти методы 100% оптимизированы, они просто для демонстрации данных

исключения выигрываются тогда и только тогда, когда число равно 4 символам или меньше, и каждая строка всегда ряд... в таком случае, зачем вообще иметь чек?

короче говоря, это очень болезненно, если вы часто сталкиваетесь с недопустимыми числами с помощью try/catch, что имеет смысл. Важное правило я всегда следуйте это никогда не используйте try / catch для потока программы. Это пример того, почему.

интересно, что простой if char 9 был чрезвычайно прост в написании, легко запоминается (и должен работать на нескольких языках) и выигрывает почти все тестовые сценарии.

единственным недостатком является то, что я предполагаю целое число.parseInt () может обрабатывать номера не ASCII, тогда как метод поиска массива этого не делает.


для тех, кто задается вопросом, почему я сказал, что это легко помните массив символов один, если вы знаете, что нет никаких отрицательных знаков, вы можете легко уйти с чем-то конденсированным, как это:

public static boolean isNumericArray(String str) {
    if (str == null)
        return false;
    for (char c : str.toCharArray())
        if (c < '0' || c > '9')
            return false;
    return true;

наконец, в качестве заключительной ноты, мне было любопытно о операторе назначения в принятом примере со всеми голосами вверх. Добавление в задание

double d = Double.parseDouble(...)

не только бесполезно, так как вы даже не используете значение, но он тратит время обработки и увеличивает время выполнения на несколько наносекунд (что привело к 100-200 МС увеличение тестов). Я не могу понять, почему кто-то будет делать это, так как на самом деле это дополнительная работа для снижения производительности.

вы думаете, что это будет оптимизировано... хотя, возможно, я должен проверить байт-код и посмотреть, что делает компилятор. Это не объясняет, почему он всегда появлялся как более длинный для меня, хотя если он каким-то образом оптимизирован... поэтому мне интересно, что происходит. Как Примечание: под более длинным я имею в виду запуск теста для 10000000 итераций и запуск этой программы несколько раз (10x+) всегда показывали, что это медленнее.

изменить: обновлен тест для персонажа.isDigit()

public static boolean isNumeric(String str)
{
    return str.matches("-?\d+(.\d+)?");
}

регулярное выражение CraigTP (показано выше) производит некоторые ложные срабатывания. Например, "23y4" будет считаться числом, потому что '.- соответствует любому символу, кроме десятичной точки.

также он будет отклонять любое число с ведущим'+'

альтернативой, которая позволяет избежать этих двух незначительных проблем является

public static boolean isNumeric(String str)
{
    return str.matches("[+-]?\d*(\.\d+)?");
}

можно использовать NumberFormat#parse:

try
{
     NumberFormat.getInstance().parse(value);
}
catch(ParseException e)
{
    // Not a number.
}

Если вы используете java для разработки приложений для Android, вы можете использовать TextUtils.isDigitsOnly

вот мой ответ на эту проблему.

метод catch all convenience, который вы можете использовать для разбора любой строки с любым типом парсера:isParsable(Object parser, String str). Парсер может быть Class или object. Это также позволит вам использовать пользовательские парсеры, которые вы написали и должны работать для любого сценария, например:

isParsable(Integer.class, "11");
isParsable(Double.class, "11.11");
Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");
isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");

вот мой код в комплекте с описаниями методов.

import java.lang.reflect.*;

/**
 * METHOD: isParsable<p><p>
 * 
 * This method will look through the methods of the specified <code>from</code> parameter
 * looking for a public method name starting with "parse" which has only one String
 * parameter.<p>
 * 
 * The <code>parser</code> parameter can be a class or an instantiated object, eg:
 * <code>Integer.class</code> or <code>new Integer(1)</code>. If you use a
 * <code>Class</code> type then only static methods are considered.<p>
 * 
 * When looping through potential methods, it first looks at the <code>Class</code> associated
 * with the <code>parser</code> parameter, then looks through the methods of the parent's class
 * followed by subsequent ancestors, using the first method that matches the criteria specified
 * above.<p>
 * 
 * This method will hide any normal parse exceptions, but throws any exceptions due to
 * programmatic errors, eg: NullPointerExceptions, etc. If you specify a <code>parser</code>
 * parameter which has no matching parse methods, a NoSuchMethodException will be thrown
 * embedded within a RuntimeException.<p><p>
 * 
 * Example:<br>
 * <code>isParsable(Boolean.class, "true");<br>
 * isParsable(Integer.class, "11");<br>
 * isParsable(Double.class, "11.11");<br>
 * Object dateFormater = new java.text.SimpleDateFormat("yyyy.MM.dd G 'at' HH:mm:ss z");<br>
 * isParsable(dateFormater, "2001.07.04 AD at 12:08:56 PDT");<br></code>
 * <p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @throws java.lang.NoSuchMethodException If no such method is accessible 
 */
public static boolean isParsable(Object parser, String str) {
    Class theClass = (parser instanceof Class? (Class)parser: parser.getClass());
    boolean staticOnly = (parser == theClass), foundAtLeastOne = false;
    Method[] methods = theClass.getMethods();

    // Loop over methods
    for (int index = 0; index < methods.length; index++) {
        Method method = methods[index];

        // If method starts with parse, is public and has one String parameter.
        // If the parser parameter was a Class, then also ensure the method is static. 
        if(method.getName().startsWith("parse") &&
            (!staticOnly || Modifier.isStatic(method.getModifiers())) &&
            Modifier.isPublic(method.getModifiers()) &&
            method.getGenericParameterTypes().length == 1 &&
            method.getGenericParameterTypes()[0] == String.class)
        {
            try {
                foundAtLeastOne = true;
                method.invoke(parser, str);
                return true; // Successfully parsed without exception
            } catch (Exception exception) {
                // If invoke problem, try a different method
                /*if(!(exception instanceof IllegalArgumentException) &&
                   !(exception instanceof IllegalAccessException) &&
                   !(exception instanceof InvocationTargetException))
                        continue; // Look for other parse methods*/

                // Parse method refuses to parse, look for another different method
                continue; // Look for other parse methods
            }
        }
    }

    // No more accessible parse method could be found.
    if(foundAtLeastOne) return false;
    else throw new RuntimeException(new NoSuchMethodException());
}


/**
 * METHOD: willParse<p><p>
 * 
 * A convienence method which calls the isParseable method, but does not throw any exceptions
 * which could be thrown through programatic errors.<p>
 * 
 * Use of {@link #isParseable(Object, String) isParseable} is recommended for use so programatic
 * errors can be caught in development, unless the value of the <code>parser</code> parameter is
 * unpredictable, or normal programtic exceptions should be ignored.<p>
 * 
 * See {@link #isParseable(Object, String) isParseable} for full description of method
 * usability.<p>
 * 
 * @param parser    The Class type or instantiated Object to find a parse method in.
 * @param str   The String you want to parse
 * 
 * @return true if a parse method was found and completed without exception
 * @see #isParseable(Object, String) for full description of method usability 
 */
public static boolean willParse(Object parser, String str) {
    try {
        return isParsable(parser, str);
    } catch(Throwable exception) {
        return false;
    }
}

чтобы соответствовать только положительным целым числам base-ten, содержащим только цифры ASCII, используйте:

public static boolean isNumeric(String maybeNumeric) {
    return maybeNumeric != null && maybeNumeric.matches("[0-9]+");
}

хорошо работающий подход, избегающий попытки поймать и обработки отрицательных чисел и научной нотации.

Pattern PATTERN = Pattern.compile( "^(-?0|-?[1-9]\d*)(\.\d+)?(E\d+)?$" );

public static boolean isNumeric( String value ) 
{
    return value != null && PATTERN.matcher( value ).matches();
}

вот мой класс для проверки, является ли строка числовой. Он также фиксирует числовые строки:

характеристики:

  1. удаляет ненужные нули ["12.0000000" -> "12"]
  2. удаляет ненужные нули ["12.0580000" -> "12.058"]
  3. удаляет нечисловые символы ["12. 00sdfsdf00" - > "12"]
  4. обрабатывает отрицательные строковые значения ["-12,020000" -> "-12.02"]
  5. удаляет несколько точек ["-12.0.20.000" -> "-12.02"]
  6. никаких дополнительных библиотек, только стандартная Java

здесь вы идете...

public class NumUtils {
    /**
     * Transforms a string to an integer. If no numerical chars returns a String "0".
     *
     * @param str
     * @return retStr
     */
    static String makeToInteger(String str) {
        String s = str;
        double d;
        d = Double.parseDouble(makeToDouble(s));
        int i = (int) (d + 0.5D);
        String retStr = String.valueOf(i);
        System.out.printf(retStr + "   ");
        return retStr;
    }

    /**
     * Transforms a string to an double. If no numerical chars returns a String "0".
     *
     * @param str
     * @return retStr
     */
    static String makeToDouble(String str) {

        Boolean dotWasFound = false;
        String orgStr = str;
        String retStr;
        int firstDotPos = 0;
        Boolean negative = false;

        //check if str is null
        if(str.length()==0){
            str="0";
        }

        //check if first sign is "-"
        if (str.charAt(0) == '-') {
            negative = true;
        }

        //check if str containg any number or else set the string to '0'
        if (!str.matches(".*\d+.*")) {
            str = "0";
        }

        //Replace ',' with '.'  (for some european users who use the ',' as decimal separator)
        str = str.replaceAll(",", ".");
        str = str.replaceAll("[^\d.]", "");

        //Removes the any second dots
        for (int i_char = 0; i_char < str.length(); i_char++) {
            if (str.charAt(i_char) == '.') {
                dotWasFound = true;
                firstDotPos = i_char;
                break;
            }
        }
        if (dotWasFound) {
            String befDot = str.substring(0, firstDotPos + 1);
            String aftDot = str.substring(firstDotPos + 1, str.length());
            aftDot = aftDot.replaceAll("\.", "");
            str = befDot + aftDot;
        }

        //Removes zeros from the begining
        double uglyMethod = Double.parseDouble(str);
        str = String.valueOf(uglyMethod);

        //Removes the .0
        str = str.replaceAll("([0-9])\.0+([^0-9]|$)", "");

        retStr = str;

        if (negative) {
            retStr = "-"+retStr;
        }

        return retStr;

    }

    static boolean isNumeric(String str) {
        try {
            double d = Double.parseDouble(str);
        } catch (NumberFormatException nfe) {
            return false;
        }
        return true;
    }

}

исключения стоят дорого, но в данном случае регулярное выражение занимает гораздо больше времени. В приведенном ниже коде показан простой тест двух функций - одна с использованием исключений и одна с использованием регулярных выражений. На моей машине регулярное выражение версии в 10 раз медленнее, чем исключение.

import java.util.Date;


public class IsNumeric {

public static boolean isNumericOne(String s) {
    return s.matches("-?\d+(\.\d+)?");  //match a number with optional '-' and decimal.      
}

public static boolean isNumericTwo(String s) {
    try {
        Double.parseDouble(s);
        return true;
    } catch (Exception e) {
        return false;
    }
}

public static void main(String [] args) {

    String test = "12345.F";

    long before = new Date().getTime();     
    for(int x=0;x<1000000;++x) {
        //isNumericTwo(test);
        isNumericOne(test);
    }
    long after = new Date().getTime();

    System.out.println(after-before);

}

}

Соответствие Регулярному Выражению

вот еще один пример обновленного регулярного выражения "CraigTP", соответствующего большему количеству проверок.

public static boolean isNumeric(String str)
{
    return str.matches("^(?:(?:\-{1})?\d+(?:\.{1}\d+)?)$");
}
  1. только один отрицательный знак - разрешено и должно быть в начале.
  2. после отрицательного знака должны быть цифрами.
  3. только один десятичный знак . допущено.
  4. после десятичного знака должны быть цифрами.

Регулярных Выражений

1                  --                   **VALID**
1.                 --                   INVALID
1..                --                   INVALID
1.1                --                   **VALID**
1.1.1              --                   INVALID

-1                 --                   **VALID**
--1                --                   INVALID
-1.                --                   INVALID
-1.1               --                   **VALID**
-1.1.1             --                   INVALID

// пожалуйста, проверьте ниже код

public static boolean isDigitsOnly(CharSequence str) {
    final int len = str.length();
    for (int i = 0; i < len; i++) {
        if (!Character.isDigit(str.charAt(i))) {
            return false;
        }
    }
    return true;
}

вот почему мне нравится подход Try* в .NET.в дополнение к традиционному методу разбора, который похож на Java, у вас также есть метод TryParse. Я не очень хорошо разбираюсь в синтаксисе Java (out parameters?), поэтому, пожалуйста, рассматривайте следующее как какой-то псевдокод. Однако это должно сделать концепцию ясной.

boolean parseInteger(String s, out int number)
{
    try {
        number = Integer.parseInt(myString);
        return true;
    } catch(NumberFormatException e) {
        return false;
    }
}

использование:

int num;
if (parseInteger("23", out num)) {
    // Do something with num.
}
// only int
public static boolean isNumber(int num) 
{
    return (num >= 48 && c <= 57); // 0 - 9
}

// is type of number including . - e E 
public static boolean isNumber(String s) 
{
    boolean isNumber = true;
    for(int i = 0; i < s.length() && isNumber; i++) 
    {
        char c = s.charAt(i);
        isNumber = isNumber & (
            (c >= '0' && c <= '9') || (c == '.') || (c == 'e') || (c == 'E') || (c == '')
        );
    }
    return isInteger;
}

// is type of number 
public static boolean isInteger(String s) 
{
    boolean isInteger = true;
    for(int i = 0; i < s.length() && isInteger; i++) 
    {
        char c = s.charAt(i);
        isInteger = isInteger & ((c >= '0' && c <= '9'));
    }
    return isInteger;
}

public static boolean isNumeric(String s) 
{
    try
    {
        Double.parseDouble(s);
        return true;
    }
    catch (Exception e) 
    {
        return false;
    }
}

Это простой пример для этой проверки:

public static boolean isNumericString(String input) {
    boolean result = false;

    if(input != null && input.length() > 0) {
        char[] charArray = input.toCharArray();

        for(char c : charArray) {
            if(c >= '0' && c <= '9') {
                // it is a digit
                result = true;
            } else {
                result = false;
                break;
            }
        }
    }

    return result;
}

разобрать его (т. е. с Integer#parseInt ) и просто поймать исключение. =)

чтобы уточнить: функция parseInt проверяет, может ли она анализировать число в любом случае (очевидно), и если вы все равно хотите его разобрать, вы не собираетесь брать какую-либо производительность, фактически выполняя разбор.

Если вы не хотите разбирать его (или разбирать его очень, очень редко), вы можете сделать это по-другому, конечно.

вы можете использовать java.утиль.Объект сканера.

public static boolean isNumeric(String inputData) {
      Scanner sc = new Scanner(inputData);
      return sc.hasNextInt();
    }

вот два метода, которые могут работать. (Без использования исключений). Примечание: Java-это значение передачи по умолчанию, а значение строки-это адрес данных объекта строки. Итак, когда вы делаете

stringNumber = stringNumber.replaceAll(" ", "");

вы изменили входное значение, чтобы иметь пробелов. Вы можете удалить эту строку, если хотите.

private boolean isValidStringNumber(String stringNumber)
{
    if(stringNumber.isEmpty())
    {
        return false;
    }

    stringNumber = stringNumber.replaceAll(" ", "");

    char [] charNumber = stringNumber.toCharArray();
    for(int i =0 ; i<charNumber.length ;i++)
    {
        if(!Character.isDigit(charNumber[i]))
        {
            return false;
        }
    }
    return true;
}

вот еще один метод в случае, если вы хотите, чтобы поплавки Этот метод якобы позволяет передавать числа в форме 1,123,123,123,123,123.123 У меня есть просто сделал это, и я думаю, что он нуждается в дальнейшем тестировании, чтобы убедиться, что он работает.

private boolean isValidStringTrueNumber(String stringNumber)
{
    if(stringNumber.isEmpty())
    {
        return false;
    }

    stringNumber = stringNumber.replaceAll(" ", "");
    int countOfDecimalPoint = 0;
    boolean decimalPointPassed = false;
    boolean commaFound = false;
    int countOfDigitsBeforeDecimalPoint = 0;
    int countOfDigitsAfterDecimalPoint =0 ;
    int commaCounter=0;
    int countOfDigitsBeforeFirstComma = 0;

    char [] charNumber = stringNumber.toCharArray();
    for(int i =0 ; i<charNumber.length ;i++)
    {
        if((commaCounter>3)||(commaCounter<0))
        {
            return false;
        }
        if(!Character.isDigit(charNumber[i]))//Char is not a digit.
        {
            if(charNumber[i]==',')
            {
                if(decimalPointPassed)
                {
                    return false;
                }
                commaFound = true;
                //check that next three chars are only digits.
                commaCounter +=3;
            }
            else if(charNumber[i]=='.')
            {
                decimalPointPassed = true;
                countOfDecimalPoint++;
            }
            else
            {
                return false;
            }
        }
        else //Char is a digit.
        {
            if ((commaCounter>=0)&&(commaFound))
            {
                if(!decimalPointPassed)
                {
                    commaCounter--;
                }
            }

            if(!commaFound)
            {
                countOfDigitsBeforeFirstComma++;
            }

            if(!decimalPointPassed)
            {
                countOfDigitsBeforeDecimalPoint++;
            }
            else
            {
                countOfDigitsAfterDecimalPoint++;
            }
        }
    }
    if((commaFound)&&(countOfDigitsBeforeFirstComma>3))
    {
        return false;
    }
    if(countOfDecimalPoint>1)
    {
        return false;
    }

    if((decimalPointPassed)&&((countOfDigitsBeforeDecimalPoint==0)||(countOfDigitsAfterDecimalPoint==0)))
    {
        return false;
    }
    return true;
}

Я изменил решение CraigTP, чтобы принять научную нотацию и точку и запятую в качестве десятичных разделителей, а также

^-?\d+([,\.]\d+)?([eE]-?\d+)?$

пример

var re = new RegExp("^-?\d+([,\.]\d+)?([eE]-?\d+)?$");
re.test("-6546"); // true
re.test("-6546355e-4456"); // true
re.test("-6546.355e-4456"); // true, though debatable
re.test("-6546.35.5e-4456"); // false
re.test("-6546.35.5e-4456.6"); // false

вы можете использовать NumberUtils.isCreatable () from Apache Commons Lang.

Начиная С NumberUtils.isNumber будет устаревшим в 4.0, поэтому используйте NumberUtils.isCreatable() вместо этого.

Это самый быстрый способ проверить, является ли строка числом или нет:

public static boolean isNumber(String str){
  int i=0, len=str.length();
  boolean a=false,b=false,c=false, d=false;
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; a=true; }
  if(i<len && (str.charAt(i)=='.')) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; b=true; }
  if(i<len && (str.charAt(i)=='e' || str.charAt(i)=='E') && (a || b)){ i++; c=true; }
  if(i<len && (str.charAt(i)=='+' || str.charAt(i)=='-') && c) i++;
  while( i<len && isDigit(str.charAt(i)) ){ i++; d=true;}
  return i==len && (a||b) && (!c || (c && d));
}
static boolean isDigit(char c){
  return c=='0' || c=='1' || c=='2' || c=='3' || c=='4' || c=='5' || c=='6' || c=='7' || c=='8' || c=='9';
}

параллельные проверки очень длинные строки с помощью IntStream

в Java 8, следующие тесты, Если все символы данного string находятся в пределах от '0' до '9'. Имейте в виду, что пустая строка принимается:

string.chars().unordered().parallel().allMatch( i -> '0' <= i && '9' >= i )

Если вы, ребята, используя следующий метод для проверки:

public static boolean isNumeric(String str) {
    NumberFormat formatter = NumberFormat.getInstance();
    ParsePosition pos = new ParsePosition(0);
    formatter.parse(str, pos);
    return str.length() == pos.getIndex();
}

тогда что произошло с вводом очень длинной строки, например, я называю этот метод:

System.out.println(isNumeric("94328948243242352525243242524243425452342343948923"));

результат "истинный", также это слишком большое число! То же самое произойдет, если вы используете регулярное выражение для проверки! Поэтому я бы предпочел использовать метод" разбора " для проверки, например:

public static boolean isNumeric(String str) {
    try {
        int number = Integer.parseInt(str);
        return true;
    } catch (Exception e) {
        return false;
    }
}

и результат, что я ожидал!

Я думаю, что единственный способ достоверно определить, является ли строка числом, - это разобрать ее. Поэтому я бы просто проанализировал его, и если это число, вы получите номер в int бесплатно!