Какой лучший способ проверить, представляет ли String целое число в Java?

214

Обычно я использую следующую идиому, чтобы проверить, можно ли преобразовать строку в целое число.

public boolean isInteger( String input ) {
    try {
        Integer.parseInt( input );
        return true;
    }
    catch( Exception e ) {
        return false;
    }
}

Это только я, или это кажется немного хакерским? Какой способ лучше?


Смотрите мой ответ (с тестами, основанные на ранее ответ по CodingWithSpike ) , чтобы понять , почему я отменил свою позицию и принял ответ Jonas Klemming по этой проблеме. Я думаю, что этот оригинальный код будет использоваться большинством людей, потому что он быстрее реализуется и более удобен в обслуживании, но он на несколько порядков медленнее, когда предоставляются нецелые данные.

Билл Ящерица
источник
Что вы думаете о RegExp для решения?
Акшай Петани

Ответы:

171

Если вас не беспокоят потенциальные проблемы переполнения, эта функция будет работать примерно в 20-30 раз быстрее, чем при использовании Integer.parseInt().

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    if (length == 0) {
        return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
        if (length == 1) {
            return false;
        }
        i = 1;
    }
    for (; i < length; i++) {
        char c = str.charAt(i);
        if (c < '0' || c > '9') {
            return false;
        }
    }
    return true;
}
Джонас К
источник
50
(c <= '/' || c> = ':') выглядит немного странно. Я бы использовал (c <'0' || c> '9') ... быстрее ли операторы <= и> = в Java?
Аноним
3
Почему бы не использовать регулярные выражения? Не возвращает ли str.matches ("^ -? \\ d + $") идентичный коду выше.
Маглоб
15
Я бы использовал этот метод или оригинальный метод из вопроса до регулярного выражения. Это для производительности, оригинальный метод для скорости реализации и абсолютной ремонтопригодности. Решение для регулярных выражений не имеет к этому никакого отношения.
Билл Ящерица
4
Я беспокоюсь о переполнении, но этот метод может быть адаптирован для BigInts и все же быть намного быстрее, чем другие методы. Если кому-то интересно, почему я прикладываю столько усилий для решения такой простой проблемы, я создаю библиотеку, которая поможет решить проблемы Project Euler.
Билл Ящерица
1
Если вас беспокоит, можете ли вы на самом деле разобрать строку в int или long, вам также необходимо проверить, соответствует ли целое число, которое представляет строка, этим типам данных.
Джонас К
65

У вас есть, но вы должны только поймать NumberFormatException.

Овидиу Пакурар
источник
7
Да, считается плохой формой ловить больше исключений, чем нужно.
Крис
Ты прав. NFE - единственный, кого можно бросить, но это все еще плохая привычка.
Билл Ящерица
Я думаю, что NPE может быть сгенерирован, если input имеет значение null, поэтому ваш метод, вероятно, должен обрабатывать это явно, в зависимости от того, что вы хотите.
Дов Вассерман
@Dov: Вы правы, NPE и NFE должны быть явно пойманы.
Билл Ящерица
Этот ответ должен быть верным ответом на этот вопрос.
Breedly
40

Сделал быстрый тест. Исключения на самом деле не такие уж и дорогие, если только вы не начнете использовать несколько методов, а JVM придется проделать большую работу, чтобы установить стек выполнения. Оставаясь в том же методе, они не плохие исполнители.

 public void RunTests()
 {
     String str = "1234567890";

     long startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByException(str);
     long endTime = System.currentTimeMillis();
     System.out.print("ByException: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByRegex(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByRegex: ");
     System.out.println(endTime - startTime);

     startTime = System.currentTimeMillis();
     for(int i = 0; i < 100000; i++)
         IsInt_ByJonas(str);
     endTime = System.currentTimeMillis();
     System.out.print("ByJonas: ");
     System.out.println(endTime - startTime);
 }

 private boolean IsInt_ByException(String str)
 {
     try
     {
         Integer.parseInt(str);
         return true;
     }
     catch(NumberFormatException nfe)
     {
         return false;
     }
 }

 private boolean IsInt_ByRegex(String str)
 {
     return str.matches("^-?\\d+$");
 }

 public boolean IsInt_ByJonas(String str)
 {
     if (str == null) {
             return false;
     }
     int length = str.length();
     if (length == 0) {
             return false;
     }
     int i = 0;
     if (str.charAt(0) == '-') {
             if (length == 1) {
                     return false;
             }
             i = 1;
     }
     for (; i < length; i++) {
             char c = str.charAt(i);
             if (c <= '/' || c >= ':') {
                     return false;
             }
     }
     return true;
 }

Вывод:

ByException: 31

ByRegex: 453 (примечание: каждый раз перекомпилировать шаблон)

ByJonas: 16

Я согласен, что решение Jonas K является самым надежным. Похоже, он выигрывает :)

CodingWithSpike
источник
13
Отличная идея для сравнения всех трех. Чтобы быть справедливым по отношению к методам Regex и Jonas, вы должны тестировать с нецелочисленными строками, поскольку именно здесь метод Integer.parseInt будет действительно замедляться.
Билл Ящерица
4
Извините, но этот тест на регулярные выражения не очень хорош. (1) Вам не нужно , чтобы сделать регулярное выражение проверки двигателя для ^и во $второй раз , так как в matchesцелом строка должна соответствовать регулярному выражению, (2) str.matchesкаждый раз , когда нужно будет создать свой собственный , Patternкоторый стоит дорого. Из соображений производительности мы должны создать такой шаблон только один раз за пределами этого метода и использовать его внутри. (3) Мы также можем создать только один объект Matcher и использовать его reset(CharSequence)для передачи пользовательских данных и возврата его matches()результата.
Пшемо
Так что что-то вроде private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }должно иметь лучшую производительность.
Пшемо
@Pshemo Integer.valueOf ("1") и Integer.valueOf ("1") выдают исключение, поэтому проверка на ^ и $ кажется разумной.
cquezel
1
@cquezel Да, но это не обязательно, так matchesкак добавляется ^и $неявно. Посмотрите на результат " 123".matches("\\d+")и "123".matches("\\d+"). Вы увидите falseи true. falseбудет возвращено, потому что строка начинается с пробела, который не позволяет ей полностью соответствовать регулярному выражению.
Пшемо
37

Так как есть вероятность, что люди все еще посещают здесь и будут смещены против Regex после тестов ... Так что я собираюсь дать обновленную версию теста с скомпилированной версией Regex. В отличие от предыдущих тестов, этот пример показывает, что решение Regex стабильно имеет хорошую производительность.

Скопировано из Билла Ящера и дополнено скомпилированной версией:

private final Pattern pattern = Pattern.compile("^-?\\d+$");

public void runTests() {
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByCompiledRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for (int i = 0; i < 100000; i++)
            IsInt_ByCompiledRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByCompiledRegex - non-integer data: ");
    System.out.println(endTime - startTime);


    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
            IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

private boolean IsInt_ByCompiledRegex(String str) {
    return pattern.matcher(str).find();
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Полученные результаты:

ByException - integer data: 45
ByException - non-integer data: 465

ByRegex - integer data: 272
ByRegex - non-integer data: 131

ByCompiledRegex - integer data: 45
ByCompiledRegex - non-integer data: 26

ByJonas - integer data: 8
ByJonas - non-integer data: 2
Felipe
источник
1
Время ByCompiledRegex должно включать компиляцию регулярного выражения в его измерении времени.
Мартин Карни
2
@MartinCarney Я изменил его и оценил компиляцию шаблонов. Очевидно, мой CPU / JIT быстрее, но если я его интерполирую обратно, время компиляции будет 336.
tedder42
2
чтобы было ясно, что 336 (мс) - это то, что происходит, когда компиляция шаблона выполняется 100к раз, как и все остальные строки. С учетом того, что это делается только один раз, его время практически равно нулю.
tedder42
Спасибо за то, что установили запись прямо во время скомпилированного регулярного выражения.
LarsH
Может быть "^[+-]?\\d+$", будет еще лучше.
Адам
34
org.apache.commons.lang.StringUtils.isNumeric 

хотя стандартная библиотека Java действительно пропускает такие вспомогательные функции

Я думаю, что Apache Commons является обязательным условием для каждого Java-программиста

Жаль, что он еще не портирован на Java5

Лукаш Бовник
источник
1
Единственная проблема с этим - переполнение: SI все еще дает вам +1 за упоминание commons-lang :)
javamonkey79
2
Другая проблема - отрицательные числа, но я тоже +1, так как, на мой взгляд, этот подход наиболее близок к хорошему решению.
Сандрис
23

Отчасти это зависит от того, что вы подразумеваете под «можно преобразовать в целое число».

Если вы имеете в виду «может быть преобразован в int в Java», то ответ от Jonas - хорошее начало, но не совсем завершает работу. Например, он пройдет 999999999999999999999999999999. Я бы добавил нормальный вызов try / catch из вашего собственного вопроса в конце метода.

Посимвольные проверки будут эффективно отклонять «не целое число» случаев, оставляя «это целое число, но Java не может его обработать», чтобы случаи были обнаружены более медленным маршрутом исключения. Вы можете сделать это немного вручную, но это будет намного сложнее.

Джон Скит
источник
17

Только один комментарий о регулярном выражении. Каждый приведенный здесь пример неверен! Если вы хотите использовать регулярные выражения, не забывайте, что компиляция шаблона занимает много времени. Это:

str.matches("^-?\\d+$")

а также это:

Pattern.matches("-?\\d+", input);

вызывает компиляцию шаблона в каждом вызове метода. Чтобы правильно его использовать следуйте:

import java.util.regex.Pattern;

/**
 * @author Rastislav Komara
 */
public class NaturalNumberChecker {
    public static final Pattern PATTERN = Pattern.compile("^\\d+$");

    boolean isNaturalNumber(CharSequence input) {
        return input != null && PATTERN.matcher(input).matches();
    }
}
Растислав Комара
источник
5
Вы можете немного повысить производительность, создав заранее Matcher и используя метод reset (), чтобы применить его к входным данным.
Алан Мур
13

Есть версия гуавы:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Он вернет ноль вместо генерации исключения, если ему не удастся проанализировать строку.

abalcerek
источник
3
Лучший ответ ИМХО. Используйте хорошо протестированные библиотеки вместо того, чтобы свернуть собственное решение. (Также см. Обсуждение здесь .)
Оливье Кайо
12

Я скопировал код из ответа rally25rs и добавил несколько тестов для нецелых данных. Результаты неоспоримо в пользу метода , публикуемую Йонас Klemming. Результаты для метода Exception, который я первоначально опубликовал, довольно хороши, когда у вас есть целочисленные данные, но они хуже, когда у вас их нет, в то время как результаты для решения RegEx (которые, я уверен, многие используют) были постоянно плохими. Смотрите ответ Фелипе для скомпилированного примера регулярных выражений, который намного быстрее.

public void runTests()
{
    String big_int = "1234567890";
    String non_int = "1234XY7890";

    long startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(big_int);
    long endTime = System.currentTimeMillis();
    System.out.print("ByException - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByException(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByException - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByRegex - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByRegex(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByRegex - non-integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(big_int);
    endTime = System.currentTimeMillis();
    System.out.print("\nByJonas - integer data: ");
    System.out.println(endTime - startTime);

    startTime = System.currentTimeMillis();
    for(int i = 0; i < 100000; i++)
        IsInt_ByJonas(non_int);
    endTime = System.currentTimeMillis();
    System.out.print("ByJonas - non-integer data: ");
    System.out.println(endTime - startTime);
}

private boolean IsInt_ByException(String str)
{
    try
    {
        Integer.parseInt(str);
        return true;
    }
    catch(NumberFormatException nfe)
    {
        return false;
    }
}

private boolean IsInt_ByRegex(String str)
{
    return str.matches("^-?\\d+$");
}

public boolean IsInt_ByJonas(String str)
{
    if (str == null) {
            return false;
    }
    int length = str.length();
    if (length == 0) {
            return false;
    }
    int i = 0;
    if (str.charAt(0) == '-') {
            if (length == 1) {
                    return false;
            }
            i = 1;
    }
    for (; i < length; i++) {
            char c = str.charAt(i);
            if (c <= '/' || c >= ':') {
                    return false;
            }
    }
    return true;
}

Полученные результаты:

ByException - integer data: 47
ByException - non-integer data: 547

ByRegex - integer data: 390
ByRegex - non-integer data: 313

ByJonas - integer data: 0
ByJonas - non-integer data: 16
Билл Ящерица
источник
6

Это короче, но короче не обязательно лучше (и оно не будет отлавливать целочисленные значения, выходящие за пределы диапазона, как указано в комментарии danatel ):

input.matches("^-?\\d+$");

Лично, поскольку реализация спекулируется в вспомогательном методе, а правильность бьет по длине, я бы просто пошел с чем-то вроде того, что у вас есть (минус перехват базового Exceptionкласса, а не NumberFormatException).

Джонни Бьюкенен
источник
1
И, возможно, \\ d {1,10}, хотя и не идеален, лучше, чем \\ d +, для ловли целых чисел Java
Maglob
6

Вы можете использовать метод совпадений строкового класса. [0-9] представляет все возможные значения, + означает, что длина должна быть не менее одного символа, а * означает, что длина может быть равна нулю или более.

boolean isNumeric = yourString.matches("[0-9]+"); // 1 or more characters long, numbers only
boolean isNumeric = yourString.matches("[0-9]*"); // 0 or more characters long, numbers only
Kaitie
источник
1
Nb этот doest не соответствует "+10" или "-10"), которые обычно включаются как действительные целые числа
Тим Уинтл
4

Как насчет:

return Pattern.matches("-?\\d+", input);
Kristian
источник
Как насчет целого числа 9999999999999999999999999999999999?
Данатель
Не забудьте проверить наличие отрицательного знака.
Джереми Рутен
Вам не нужно привязывать начало и конец регулярного выражения, чтобы не пропустить "aaa-1999zzz"?
Тим Хоулэнд
2
Тим, когда вы вызываете один из методов match () (каждый из которых имеет String, Pattern и Matcher), регулярное выражение должно соответствовать всему входному значению, делая якоря избыточными. Чтобы найти соответствие, определенное большинством других разновидностей регулярных выражений, вы должны использовать Matcher # find ().
Алан Мур
4

Это вариант ответа Jonas Klemming на Java 8:

public static boolean isInteger(String str) {
    return str != null && str.length() > 0 &&
         IntStream.range(0, str.length()).allMatch(i -> i == 0 && (str.charAt(i) == '-' || str.charAt(i) == '+')
                  || Character.isDigit(str.charAt(i)));
}

Тестовый код:

public static void main(String[] args) throws NoSuchAlgorithmException, UnsupportedEncodingException {
    Arrays.asList("1231231", "-1232312312", "+12313123131", "qwqe123123211", "2", "0000000001111", "", "123-", "++123",
            "123-23", null, "+-123").forEach(s -> {
        System.out.printf("%15s %s%n", s, isInteger(s));
    });
}

Результаты теста кода:

        1231231 true
    -1232312312 true
   +12313123131 true
  qwqe123123211 false
              2 true
  0000000001111 true
                false
           123- false
          ++123 false
         123-23 false
           null false
          +-123 false
gil.fernandes
источник
3

Вы просто проверяете NumberFormatException : -

 String value="123";
 try  
 {  
    int s=Integer.parseInt(any_int_val);
    // do something when integer values comes 
 }  
 catch(NumberFormatException nfe)  
 {  
          // do something when string values comes 
 }  
Дуггу
источник
3

Если ваш массив String содержит чистые целые числа и строки, код ниже должен работать. Вам нужно только взглянуть на первого персонажа. например, ["4", "44", "abc", "77", "bond"]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}
realPK
источник
3

Вы также можете использовать класс Scanner и использовать hasNextInt () - и это позволяет вам проверять и другие типы, такие как float и т. Д.

Мэтью Шинкель
источник
Этот ответ дал мне напоминание, в котором я нуждался. Я полностью забыл, что у Сканера была такая функция. T-Up
Hubro
2

Если вы хотите проверить, представляет ли строка целое число, которое соответствует типу int, я немного изменил ответ jonas, чтобы строки, представляющие целые числа, большие, чем Integer.MAX_VALUE, или меньше, чем Integer.MIN_VALUE, теперь возвращали ложный. Например: «3147483647» вернет false, потому что 3147483647 больше, чем 2147483647, и аналогично «-2147483649» также вернет false, потому что -2147483649 меньше, чем -2147483648.

public static boolean isInt(String s) {
  if(s == null) {
    return false;
  }
  s = s.trim(); //Don't get tricked by whitespaces.
  int len = s.length();
  if(len == 0) {
    return false;
  }
  //The bottom limit of an int is -2147483648 which is 11 chars long.
  //[note that the upper limit (2147483647) is only 10 chars long]
  //Thus any string with more than 11 chars, even if represents a valid integer, 
  //it won't fit in an int.
  if(len > 11) {
    return false;
  }
  char c = s.charAt(0);
  int i = 0;
  //I don't mind the plus sign, so "+13" will return true.
  if(c == '-' || c == '+') {
    //A single "+" or "-" is not a valid integer.
    if(len == 1) {
      return false;
    }
    i = 1;
  }
  //Check if all chars are digits
  for(; i < len; i++) {
    c = s.charAt(i);
    if(c < '0' || c > '9') {
      return false;
    }
  }
  //If we reached this point then we know for sure that the string has at
  //most 11 chars and that they're all digits (the first one might be a '+'
  // or '-' thought).
  //Now we just need to check, for 10 and 11 chars long strings, if the numbers
  //represented by the them don't surpass the limits.
  c = s.charAt(0);
  char l;
  String limit;
  if(len == 10 && c != '-' && c != '+') {
    limit = "2147483647";
    //Now we are going to compare each char of the string with the char in
    //the limit string that has the same index, so if the string is "ABC" and
    //the limit string is "DEF" then we are gonna compare A to D, B to E and so on.
    //c is the current string's char and l is the corresponding limit's char
    //Note that the loop only continues if c == l. Now imagine that our string
    //is "2150000000", 2 == 2 (next), 1 == 1 (next), 5 > 4 as you can see,
    //because 5 > 4 we can guarantee that the string will represent a bigger integer.
    //Similarly, if our string was "2139999999", when we find out that 3 < 4,
    //we can also guarantee that the integer represented will fit in an int.
    for(i = 0; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  c = s.charAt(0);
  if(len == 11) {
    //If the first char is neither '+' nor '-' then 11 digits represent a 
    //bigger integer than 2147483647 (10 digits).
    if(c != '+' && c != '-') {
      return false;
    }
    limit = (c == '-') ? "-2147483648" : "+2147483647";
    //Here we're applying the same logic that we applied in the previous case
    //ignoring the first char.
    for(i = 1; i < len; i++) {
      c = s.charAt(i);
      l = limit.charAt(i);
      if(c > l) {
        return false;
      }
      if(c < l) {
        return true;
      }
    }
  }
  //The string passed all tests, so it must represent a number that fits
  //in an int...
  return true;
}

источник
1
Можете ли вы отредактировать свой ответ и объяснить, как он улучшает предыдущий ответ, который вы упомянули?
Жиль Гуаиллардет
Спасибо за отличный ответ. Но «123», то есть 123 вместе с пробелом, считается действительным целым числом.
Сайкришна Радарапу
1
@SaikrishnaRadarapu Они используют, trim()так что это явно преднамеренный выбор дизайна.
Гильденстерн
2

Вы можете попробовать утилиты apache

NumberUtils.isCreatable(myText)

Смотрите Javadoc здесь

borjab
источник
1
Кажется, что этот метод устарел в последней версии ссылки ). Видимо, вы должны использовать isCreateable(String)вместо этого.
Гильденстерн
Обновлено. Спасибо @Guildenstern
Борхаб
1

Вы, вероятно, должны принять во внимание также вариант использования:

Если большую часть времени вы ожидаете, что числа будут действительными, то перехват исключения приводит только к снижению производительности при попытке преобразовать недопустимые числа. Принимая во внимание , вызывая некоторый isInteger()метод , а затем преобразовать , используя Integer.parseInt()будет всегда причиной над головой производительности для действительных чисел - строки обрабатываются дважды, один раз чек и один раз преобразования.

mobra66
источник
1

Это модификация кода Джонаса , который проверяет, находится ли строка в пределах диапазона, который будет приведен к целому числу.

public static boolean isInteger(String str) {
    if (str == null) {
        return false;
    }
    int length = str.length();
    int i = 0;

    // set the length and value for highest positive int or lowest negative int
    int maxlength = 10;
    String maxnum = String.valueOf(Integer.MAX_VALUE);
    if (str.charAt(0) == '-') { 
        maxlength = 11;
        i = 1;
        maxnum = String.valueOf(Integer.MIN_VALUE);
    }  

    // verify digit length does not exceed int range
    if (length > maxlength) { 
        return false; 
    }

    // verify that all characters are numbers
    if (maxlength == 11 && length == 1) {
        return false;
    }
    for (int num = i; num < length; num++) {
        char c = str.charAt(num);
        if (c < '0' || c > '9') {
            return false;
        }
    }

    // verify that number value is within int range
    if (length == maxlength) {
        for (; i < length; i++) {
            if (str.charAt(i) < maxnum.charAt(i)) {
                return true;
            }
            else if (str.charAt(i) > maxnum.charAt(i)) {
                return false;
            }
        }
    }
    return true;
}
Wayne
источник
1
выглядит хорошо, но последний цикл for должен иметь i, сбрасываемый в ноль (или 1, если отрицательное число), потому что цикл, который проверяет, является ли каждая цифра числом, приведет к тому, что я - длина строки, следовательно, последний цикл for никогда не побежит Я бы также использовал Java-константы Integer.MAX_VALUE и Integer.MIN_VALUE вместо магических чисел.
Тим Чародей
@TimtheEnchanter Спасибо за предложения, я их полностью пропустил. В своем редактировании, чтобы включить их, я использовал новую переменную в первом цикле for, чтобы избежать лишнего оператора if.
Уэйн
1

Если вы используете Android API, вы можете использовать:

TextUtils.isDigitsOnly(str);
timxyz
источник
1

Другой вариант:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}
Габриэль Каффка
источник
0
is_number = true;
try {
  Integer.parseInt(mystr)
} catch (NumberFormatException  e) {
  is_number = false;
}
Рикардо Акрас
источник
5
Это делает то же самое, о чем спрашивает плакат.
Мартин Карни
0

То, что вы сделали, работает, но вы, вероятно, не всегда должны проверять это. Броски исключений должны быть зарезервированы для «исключительных» ситуаций (возможно, это подходит для вашего случая), и они очень дороги с точки зрения производительности.

Лукас
источник
Они только дорогостоящие, если их бросают.
Билл Ящерица
0
Number number;
try {
    number = NumberFormat.getInstance().parse("123");
} catch (ParseException e) {
    //not a number - do recovery.
    e.printStackTrace();
}
//use number
Ран Бирон
источник
0

Это будет работать только для натуральных чисел.

public static boolean isInt(String str) {
    if (str != null && str.length() != 0) {
        for (int i = 0; i < str.length(); i++) {
            if (!Character.isDigit(str.charAt(i))) return false;
        }
    }
    return true;        
}
оборота Callejero
источник
4
Добро пожаловать в stackoverflow. Перед воскрешением старой темы обязательно прочитайте предыдущие ответы и комментарии. Этот метод (и возможные недостатки) фактически уже обсуждались.
Ли
0

Это работает для меня. Просто чтобы определить, является ли String примитивом или числом.

private boolean isPrimitive(String value){
        boolean status=true;
        if(value.length()<1)
            return false;
        for(int i = 0;i<value.length();i++){
            char c=value.charAt(i);
            if(Character.isDigit(c) || c=='.'){

            }else{
                status=false;
                break;
            }
        }
        return status;
    }
Нирошан Абейвикрама
источник
0

Чтобы проверить все int-символы, вы можете просто использовать двойной минус.

if (! searchString.matches ("[^ 0-9] + $")) ...

[^ 0-9] + $ проверяет, есть ли какие-либо символы, которые не являются целочисленными, поэтому проверка завершается неудачно, если это правда. Просто НЕ это, и вы получите успех.

Роджер Ф. Гей
источник
Нет. Вы явно не проверяли это. Это возвращает true, только если где-то в строке есть цифра, а не если строка состоит только из цифр. matchesМетод соответствует против всей строки, а не только часть его.
Дауд ибн Карим
Вы не получите двойную отрицательную часть.
Роджер Ф. Гей,
Ну, я НЕ получаю двойной негатив. Это просто не работает. Если у вас есть смесь цифр и букв, это идет в ifблок. Это не должно
Дауд ибн Карим
0

Найти это может быть полезным:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}
shellbye
источник
0

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

Так:

  1. Вы проверяете, соответствует ли каждый слот символа в вашей строке хотя бы одному из символов {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. Вы суммируете все времена, которые встречали в слотах вышеперечисленных символов.

    digits++;
  3. И, наконец, вы проверяете, совпадает ли время, в которое вы встречали целые числа как символы, с длиной заданной строки.

    if(digits == aString.length())

И на практике имеем:

    String aString = "1234224245";
    int digits = 0;//count how many digits you encountered
    for(int j=0;j<aString.length();j++){
        for(int i=0;i<=9;i++){
            if(aString.substring(j, j+1).equals(String.valueOf(i)))
                    digits++;
        }
    }
    if(digits == aString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }
    
    String anotherString = "1234f22a4245";
    int anotherDigits = 0;//count how many digits you encountered
    for(int j=0;j<anotherString.length();j++){
        for(int i=0;i<=9;i++){
            if(anotherString.substring(j, j+1).equals(String.valueOf(i)))
                    anotherDigits++;
        }
    }
    if(anotherDigits == anotherString.length()){
        System.out.println("It's an integer!!");
        }
    else{
        System.out.println("It's not an integer!!");
    }

И результаты:

Это целое число!

Это не целое число!

Точно так же вы можете проверить, Stringявляется ли a floatили a, doubleно в этих случаях вам нужно встретиться только с одним. (точка) в строке и, конечно, проверьте, если digits == (aString.length()-1)

Опять же, здесь нет риска столкнуться с исключением при синтаксическом анализе, но если вы планируете выполнить синтаксический анализ известной строки, содержащей число (скажем, int типа данных), вы должны сначала проверить, соответствует ли оно типу данных. В противном случае вы должны разыграть его.

Надеюсь я помог

mark_infinite
источник