Який найкращий спосіб перевірити, чи рядок представляє ціле число в Java?


214

Я зазвичай використовую наступну ідіому, щоб перевірити, чи може String можна перетворити на ціле число.

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 може бути викинуто, якщо введення недійсне, тому ваш метод, ймовірно, повинен обробляти це явно, у будь-який спосіб ви хочете.
Дов Васерман

@Dov: Ви маєте рацію, що NPE і NFE повинні бути чітко спіймані.
Білл Ящірка

Ця відповідь повинна бути справжньою відповіддю на це питання.
Приблизно

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;
 }

Вихід:

По Прикметі: 31

ByRegex: 453 (зверніть увагу: повторне складання шаблону кожен раз)

ByJonas: 16

Я погоджуюсь, що рішення Йонаса К також є найбільш надійним. Схоже, він перемагає :)


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

1
Час ByCompiledRegex повинен включати компіляцію регулярного виразу в його вимірювання часу.
Мартін Керні

2
@MartinCarney Я змінив його і склав орієнтир зразків. Очевидно, мій процесор / JIT швидший, але якщо я його інтерполюю назад, час компіляції - це 336.
tedder42

2
щоб було зрозуміло, що 336 (мс) - це те, що відбувається, коли компіляція шаблону робиться 100 к разів, як і всі інші рядки. Маючи на увазі, що це робиться лише один раз, час його в основному дорівнює нулю.
tedder42

Дякуємо, що встановили запис прямо на складеному регулярному виразі.
LarsH

Можливо, "^[+-]?\\d+$"було б ще краще.
Адам

34
org.apache.commons.lang.StringUtils.isNumeric 

хоча стандартний лідер Java справді не вистачає таких функцій утиліти

Я думаю, що Apache Commons - це "must have" для кожного Java-програміста

шкода, що він ще не перенесений на Java5


1
Єдина проблема з цим - це переповнення: SI все ж дають вам +1 за згадування commons-lang :)
javamonkey79

2
Інша проблема - негативні цифри, але я також +1, оскільки, на мій погляд, такий підхід наближається до хорошого рішення.
сандріс

22

Частково це залежить від того, що ви маєте на увазі під "можна перетворити на ціле число".

Якщо ви маєте на увазі "можна перетворити на int на Java", то відповідь від Jonas - це хороший початок, але це не зовсім закінчить роботу. Наприклад, пройде 9999999999999999999999999999999. Я б додав звичайний виклик "try / catch" з вашого власного запитання в кінці методу.

Перевірки символів за символом ефективно відхилять випадки "не ціле число взагалі", залишаючи "це ціле число, але Java не може впоратися з ним" випадки, які будуть спіймані повільнішим маршрутом виключення. Ви можете це зробити і вручну, але це було б набагато складніше.


17

Лише один коментар про regexp. Кожен наведений тут приклад - неправильний !. Якщо ви хочете використовувати regexp, не забувайте, що на складання шаблону потрібно багато часу. Це:

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
Ви можете вичавити трохи більше продуктивності, створивши Матчер достроково, використовуючи метод reset (), щоб застосувати його до вводу.
Алан Мур

13

Є версія guava:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Він поверне null замість викидання винятку, якщо не вдасться розібрати рядок.


3
Найкраща відповідь ІМХО. Використовуйте добре перевірені бібліотеки замість того, щоб розгорнути власне рішення. (Також дивіться дискусію тут .)
Олів'є Кайло

12

Я скопіював код з відповіді rally25rs і додав кілька тестів на не цілі дані. Результати, безперечно, на користь методу, розміщеного Йонасом Клеммінгом. Результати методу «Виняток», який я спочатку розмістив, досить хороші, коли у вас є цілі дані, але вони найгірші, коли у вас немає, в той час як результати для рішення 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
Integers

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

1
Nb цей знак не відповідає "+10" або "-10"), які, як правило, включатимуться як дійсні цілі числа
Тім Вінтл

4

Як щодо:

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

Що з цілим числом 999999999999999999999999999999999999?
danatel

Не забудьте перевірити наявність негативного знаку.
Джеремі Рутен

вам не потрібно прив’язувати початок і кінець регулярного виразу, щоб ви не пройшли "aaa-1999zzz"?
Тім Хоуленд

2
Тим, коли ви викликаєте один із методів match () (у String, Pattern і Matcher є один), регулярний вираз повинен відповідати всьому вводу, що робить якір зайвим. Щоб знайти відповідність, як визначено більшістю інших ароматів регулярних виразів, вам потрібно використовувати Matcher # find ().
Алан Мур

4

Це варіант відповіді Джона Клемінга на 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

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
}

3

Ви також можете скористатися класом Scanner і використовувати hasNextInt () - і це дозволяє також протестувати на інші типи, наприклад, floats тощо.


Ця відповідь дала мені нагадування, яке мені потрібно. Я повністю забув, що Сканер мав таку функцію. T-up
Hubro

2

Якщо ви хочете перевірити, чи являє собою рядок ціле число, яке відповідає типу int, я зробив невелику модифікацію відповіді jonas, щоб рядки, що представляють цілі числа, більші за Integer.MAX_VALUE або менші за Integer.MIN_VALUE, тепер повернуться помилковий. Наприклад: "3147483647" поверне помилковим, оскільки 3147483647 більше, ніж 2147483647, і "-2147483649" також поверне помилковим, оскільки -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()так, що це, очевидно, навмисний вибір дизайну.
Гільденстерн


1

Вам, мабуть, потрібно також врахувати справу використання:

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


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;
}

1
виглядає добре, але для останнього циклу for я повинен бути скинутий до нуля (або 1, якщо від'ємне число), оскільки цикл, який перевіряє, чи є кожна цифра числом, призведе до того, що я буде довжиною рядка, тому останній цикл for ніколи не біжить. Я б також використовував константи Java Integer.MAX_VALUE і Integer.MIN_VALUE замість магічних чисел.
Тім Чарівник

@TimtheEnchanter Дякую за пропозиції, я повністю їх не помітив. У своєму редагуванні для їх включення я використав нову змінну в першій для циклу, щоб уникнути додаткового оператора if.
Уейн

1

Якщо ви використовуєте API Android, ви можете використовувати:

TextUtils.isDigitsOnly(str);

1

Ще один варіант:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}


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;        
}

4
Ласкаво просимо в stackoverflow. Перш ніж воскресити стару нитку, обов'язково прочитайте попередні відповіді та коментарі. Цей метод (та можливі недоліки) вже фактично обговорювались.
Лі

0

Це працює для мене. Просто визначити, чи є рядок примітивним чи числом.

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] + $ перевіряє, чи є якісь символи, які не є цілими, тому тест завершується, якщо це правда. Тільки НЕ це, і ти справдишся успіхом.


Ні. Ви цього очевидно не перевіряли. Це повертає істину лише в тому випадку, якщо десь у рядку є цифра, а не якщо рядок є лише цифрами. matchesМетод відповідає проти всього рядка, а не тільки частина його.
Давуд ібн Карім

Ви не отримуєте подвійної негативної частини.
Роджер Ф. Гей

Ну, я не отримую подвійного негативу. Це просто не працює. Якщо у вас суміш цифр і букв, це переходить у ifблок. Це не повинно.
Давуд ібн Карім

0

Знайти це може корисно:

public static boolean isInteger(String self) {
    try {
        Integer.valueOf(self.trim());
        return true;
    } catch (NumberFormatException nfe) {
        return false;
    }
}

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 ), спершу потрібно перевірити, чи відповідає він типу даних. В іншому випадку ви повинні її віддати.

Сподіваюся, я допоміг

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.