我通常使用以下惯用法来检查是否可以将String转换为整数。

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


这只是我一个人吗,或者这看起来有点黑吗?有什么更好的方法?


查看我的答案(带有基准,基于先前CodingWithSpike的答案),以了解为什么我改变了立场并接受了乔纳斯·克林明(Jonas Klemming)对这个问题的答案。我认为大多数人会使用此原始代码,因为它实现起来更快,更易于维护,但是在提供非整数数据时,它的速度要慢几个数量级。

评论

您对RegExp解决方案有何想法?

#1 楼

如果您不担心潜在的溢出问题,则此功能的执行速度将比使用Integer.parseInt()快20-30倍。

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


评论


(c <='/'|| c> =':')看起来有点奇怪。我本来会用(c <'0'|| c>'9')...在Java中<=和> =运算符是否更快?

–匿名
08-10-26在1:43

为什么不使用正则表达式?返回的str.matches(“ ^-?\\ d + $”)是否与上面的代码相同。

– Maglob
08-10-26在9:28

我会使用此方法或正则表达式之前的问题中的原始方法。这是性能,是实现速度和纯粹的可维护性的原始方法。正则表达式解决方案无济于事。

–比尔蜥蜴
08-10-26在13:19

我担心溢出,但是此方法可以适用于BigInts,并且仍然比其他方法更快。如果有人想知道为什么我要花这么大的精力解决这个简单的问题,我会创建一个库来帮助解决Euler项目的问题。

–比尔蜥蜴
08-10-26在13:25

如果您担心是否可以将字符串实际解析为int或long类型,则还需要检查字符串表示的整数是否真正适合这些数据类型。

–乔纳斯·K(Jonas K)
2014年9月29日在9:48

#2 楼

您已经拥有了,但是只应该抓住NumberFormatException

评论


是的,捕获比您需要更多的异常被认为是不好的形式。

–克里斯
08-10-26在1:28

你是对的。 NFE是唯一可以抛出的错误,但要养成这种习惯仍然不好。

–比尔蜥蜴
08-10-26在3:26

我认为如果输入为null,则可以引发NPE,因此您的方法可能应该显式地处理该NPE,无论您采用哪种方式。

– Dov Wasserman
08-10-26在8:07

@Dov:您是对的,应该同时明确捕获NPE和NFE。

–比尔蜥蜴
08-10-26在12:35

这个回答应该是对这个问题的真正答案。


2012-2-10的3:51

#3 楼

做一个快速基准测试。异常实际上并不昂贵,除非您开始弹出多个方法,并且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


我同意乔纳斯·K的解决方案也是最强大的看起来他赢了:)

评论


对这三个进行基准测试的好主意。公平地对待Regex和Jonas方法,应该使用非整数字符串进行测试,因为这是Integer.parseInt方法将真正放慢速度的地方。

–比尔蜥蜴
08-10-26在13:00

抱歉,此正则表达式测试不好。 (1)您不需要第二次检查^和$,因为在匹配中整个字符串必须与regex匹配,(2)每次str.matches都必须创建自己的Pattern,这很昂贵。出于性能原因,我们只应在此方法外部创建一次这样的Pattern,然后在内部使用它。 (3)我们也只能创建一个Matcher对象,并使用其reset(CharSequence)传递用户数据并返回其match()结果。

– Pshemo
2013年11月6日15:01

所以像私有的最终匹配器m = Pattern.compile(“-?\\ d +”)。matcher(“”);私有布尔值byRegex(String str){return m.reset(str).matches(); }应该有更好的性能。

– Pshemo
2013年11月6日15:02

@Pshemo Integer.valueOf(“ 1”)和Integer.valueOf(“ 1”)都抛出异常,因此检查^和$似乎很合理。

–cquezel
15年5月12日在17:33

@cquezel是的,但不是必需的,因为匹配项将隐式添加^和$。看一下“ 123” .matches(“ \\ d +”)和“ 123” .matches(“ \\ d +”)的结果。您将看到错误和真实。将返回false,因为字符串以空格开头,从而使正则表达式无法完全匹配它。

– Pshemo
15年5月12日在18:07

#4 楼

由于有可能人们仍然会来这里访问,并且在基准测试之后会对Regex持偏见...所以我要提供基准测试的更新版本和Regex的编译版本。与以前的基准测试相反,此示例显示Regex解决方案实际上一直具有良好的性能。

从蜥蜴人比尔(Bill the Lizard)复制并更新为已编译版本:

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


评论


ByCompiledRegex时间需要在其时间度量中包括编译正则表达式。

–马丁·卡尼(Martin Carney)
2013年12月23日20:53

@MartinCarney我对其进行了修改并对模式编译进行了基准测试。显然,我的CPU / JIT速度更快,但是如果将其内插,则编译时间为336。

–tedder42
2014年10月8日23:26

需要明确的是,当模式编译完成10万次时,与所有其他行一样,发生336(ms)。暗示它只做一次,它的时间基本上为零。

–tedder42
2014年10月8日23:50

感谢您直接在已编译的正则表达式时间设置记录。

– LarsH
16-11-30在6:50

也许“ ^ [+-]?\\ d + $”会更好。

–亚当
17年5月15日在10:54

#5 楼

org.apache.commons.lang.StringUtils.isNumeric 


尽管Java的标准库确实错过了这些实用程序功能

我认为Apache Commons是每个Java程序员的“必不可少的”

不好,它还没有移植到Java5

评论


唯一的问题是溢出:S我仍然给您+1提到commons-lang :)

–javamonkey79
10年7月27日在23:55

另一个问题是负数,但我也+1,因为我认为这种方法最接近一种好的解决方案。

–桑德里斯
13年1月9日在7:38

#6 楼

这部分取决于您所说的“可以转换为整数”的意思。

如果您的意思是“可以用Java转换为int”,那么Jonas的答案是一个很好的开始,但没有尚未完全完成工作。例如,它将通过9999999999999999999999999999999999。我会在方法末尾添加来自您自己问题的普通try / catch调用。

逐字符检查将有效地拒绝“根本不是整数”的情况,而将“一个整数,但Java无法处理它”的情况将被较慢的异常路由捕获。您也可以手动完成此操作,但这会复杂得多。

#7 楼

关于正则表达式的一则评论。这里提供的每个示例都是错误的!如果要使用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();
    }
}


评论


您也可以提前创建Matcher,并使用其reset()方法将其应用于输入,从而提高性能。

–艾伦·摩尔
08-10-27在5:43

#8 楼

有番石榴版本:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);


如果解析字符串失败,它将返回null而不是引发异常。

评论


最佳答案恕我直言。使用经过良好测试的库,而不要汇总自己的解决方案。 (另请参见此处的讨论。)

–奥利维尔·卡柳克斯(Olivier Cailloux)
17年8月25日在11:47

#9 楼

我从rally25rs答案中复制了代码,并为非整数数据添加了一些测试。结果无可否认地支持Jonas Klemming发表的方法。当您拥有整数数据时,我最初发布的Exception方法的结果非常好,但是当您没有整数数据时,结果最差,而RegEx解决方案的结果(我敢打赌,很多人会使用)一直很糟糕。请参阅Felipe的答案,以获得编译的正则表达式示例,该示例要快得多。

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


#10 楼

它更短,但是更短不一定更好(并且不会捕获超出范围的整数值,如danatel的注释中所指出的那样):

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


个人而言,由于实现是通过辅助方法来完成的,并且正确性胜过长度,所以我会选择类似您所拥有的东西(减去捕获基本Exception类而不是NumberFormatException)。

评论


也许\\ d {1,10}尽管不完美,但在捕获Java整数方面比\\ d +好

– Maglob
08-10-25在23:15

#11 楼

您可以使用字符串类的matchs方法。 [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


评论


Nb,它与“ +10”或“ -10”不匹配),通常将其作为有效整数包含在内

– Tim Wintle
15年4月27日在15:05

#12 楼

怎么样:

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


评论


整数9999999999999999999999999999999999怎么样?

– danatel
08-10-25在23:06

不要忘记检查负号。

–杰里米·鲁滕(Jeremy Ruten)
08-10-25在23:06

您是否不需要锚定正则表达式的开头和结尾,以免传递“ aaa-1999zzz”?

–蒂姆·霍兰德
08-10-26在13:08

蒂姆,当您调用matches()方法之一(字符串,模式和匹配器各有一个)时,正则表达式必须匹配整个输入,从而使锚点变得多余。要找到大多数其他正则表达式风格定义的匹配项,必须使用Matcher#find()。

–艾伦·摩尔
08-10-27在5:23

#13 楼

这是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


#14 楼

您只需检查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 
 }  


#15 楼

如果您的String数组包含纯Integer和String,则下面的代码应该可用。您只需要看第一个字符即可。
例如[“ 4”,“ 44”,“ abc”,“ 77”,“ bond”]

if (Character.isDigit(string.charAt(0))) {
    //Do something with int
}


#16 楼

您还可以使用Scanner类,并使用hasNextInt()-这还允许您测试其他类型,例如浮点数等。

评论


这个答案给了我必要的提醒。我完全忘记了Scanner具有这样的功能。 T型

–Hubro
2010-10-26 14:15

#17 楼

如果要检查字符串是否表示适合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;
}


评论


您能否编辑您的答案并解释它如何改善您先前提到的答案?

– Gilles Gouaillardet
17年8月25日在2:26

感谢您的出色回答。但是,“ 123”,即123与空格一起被视为有效整数。

– Saikrishna Radarapu
18-4-20在8:37



@SaikrishnaRadarapu他们使用trim()显然是故意的设计选择。

– Guildstern
6月20日22:08

#18 楼

您可以尝试apache utils

NumberUtils.isCreatable(myText)


在此处查看javadoc

评论


似乎在最新版本的链接中不赞成使用此方法。显然,您应该改用isCreateable(String)。

– Guildstern
6月19日11:36

更新。谢谢@Guildenstern

– Borjab
6月19日12:23



#19 楼

您可能还需要考虑用例:

如果大多数时候您希望数字有效,那么捕获异常只会在尝试转换无效数字时引起性能开销。调用某些isInteger()方法然后使用Integer.parseInt()进行转换将始终导致有效数字的性能开销-字符串被解析两次,一次由检查,一次由转换。

#20 楼

这是Jonas代码的修改形式,该代码检查字符串是否在要转换为整数的范围内。

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


评论


看起来不错,但最后一个for循环需要将i重置为零(如果负数则为1),因为检查每个数字是否为数字的循环将导致i为字符串长度,因此最后一个for循环永远不会运行。我还将使用Java常量Integer.MAX_VALUE和Integer.MIN_VALUE代替魔术数字。

–魔法师蒂姆
2014年8月21日15:42

@TimtheEnchanter谢谢您的建议,我完全忽略了它们。在合并它们的编辑中,我在第一个for循环中使用了一个新变量,以避免多余的if语句。

–韦恩
2014年8月21日在16:47



#21 楼

如果您使用的是Android API,则可以使用:

TextUtils.isDigitsOnly(str);


#22 楼

我相信发生异常的风险为零,因为正如您在下面看到的那样,您始终可以安全地将int解析为String,而不是相反。
因此:


您检查如果您字符串中的每个字符槽都至少匹配
一个字符{“ 0”,“ 1”,“ 2”,“ 3”,“ 4”,“ 5”,“ 6”,“ 7” “,” 8“,” 9“}。
if(aString.substring(j, j+1).equals(String.valueOf(i)))



您总结上述字符在插槽中遇到的所有时间。
>
digits++;



最后,您检查遇到整数的时间是否等于给定字符串的长度。
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!!");
    }

结果是:

它是整数!
这不是整数!

同样,您可以验证Stringfloat还是double,但在这些情况下,您只需遇到一个。字符串中的(点),当然还要检查digits == (aString.length()-1)

再一次,这里遇到解析异常的风险为零,但是如果您打算解析一个已知包含数字的字符串(让我们例如int数据类型),则必须首先检查它是否适合该数据类型。否则,您必须进行投射。

我希望我能提供帮助

#23 楼

另一种选择:

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


#24 楼

您所做的工作有效,但您可能不应该总是这样检查。应该为“异常”情况保留抛出异常(尽管可能适合您的情况),并且在性能方面非常昂贵。

评论


它们只有扔掉才昂贵。

–比尔蜥蜴
08-10-26在12:52

#25 楼

这仅适用于正整数。

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


评论


欢迎使用stackoverflow。在复活旧线程之前,请确保已阅读之前的答复和评论。实际上已经讨论了这种方法(以及可能的缺点)。

– eigh
2012年3月31日0:20在

#26 楼

这对我有用。只需识别一个字符串是原始数还是数字即可。

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


#27 楼

要检查所有int字符,您可以简单地使用double负数。

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

[^ 0-9] + $检查是否有任何不是整数的字符,因此如果为真,则测试将失败。只是不这样,您就成功了。

评论


不。您显然还没有测试过。仅当字符串中某处有一个数字时,才返回true;否则,如果字符串仅是数字,则不返回。 matchs方法匹配整个字符串,而不只是其中一部分。

–达伍德·伊本·卡里姆(Dawood ibn Kareem)
18年7月22日在20:02

您不会得到双重否定部分。

–罗杰·盖伊
18年7月23日在22:28

好吧,我没有得到双重否定。这根本行不通。如果您混合使用数字和字母,则将其放入if块。不应该这样

–达伍德·伊本·卡里姆(Dawood ibn Kareem)
18年7月23日在23:21

#28 楼

我在这里看到了很多答案,但是大多数答案都可以确定String是否为数字,但是他们无法检查数字是否在Integer范围内...

因此,我的目的类似于this:

public static boolean isInteger(String str) {
    if (str == null || str.isEmpty()) {
        return false;
    }
    try {
        long value = Long.valueOf(str);
        return value >= -2147483648 && value <= 2147483647;
    } catch (Exception ex) {
        return false;
    }
}


评论


好点,由番石榴答案中建议的com.google.common.primitives.Ints.tryParse(String,int)处理。

–艾德里安·贝克(Adrian Baker)
17年1月16日在8:03

但是字符串值也有可能超过长限制。我们怎么能假设它在长距离内。例如,字符串也可以保留此值9,223,372,036,854,775,809,但是长久不能在这种情况下获得NumberFormatException。

–srinivas
19/12/6在3:45



该方法应检查,由String表示的值是否在Integer范围内。如果为该方法提供的参数甚至比Long长,那么它肯定不是整数,并且该方法应返回“ false”。这样做是因为转换会引发错误,然后catch子句将提供“ false”。

–艾洛希尔
19/12/13在15:15

#29 楼

当解释比性能更重要时,我注意到许多讨论都集中在某些解决方案的效率上,但没有一个关于为什么字符串不是整数的讨论。而且,每个人似乎都假定数字“ 2.00”不等于“ 2”。从数学和人类的角度来看,它们是相等的(即使计算机科学说它们不是,并且有充分的理由)。这就是为什么上面的“ Integer.parseInt”解决方案比较弱(取决于您的要求)的原因。
无论如何,要使软件更智能,更人性化,我们需要创建具有以下特点的软件:我们这样做并解释了为什么失败了。在这种情况下:

public static boolean isIntegerFromDecimalString(String possibleInteger) {
possibleInteger = possibleInteger.trim();
try {
    // Integer parsing works great for "regular" integers like 42 or 13.
    int num = Integer.parseInt(possibleInteger);
    System.out.println("The possibleInteger="+possibleInteger+" is a pure integer.");
    return true;
} catch (NumberFormatException e) {
    if (possibleInteger.equals(".")) {
        System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it is only a decimal point.");
        return false;
    } else if (possibleInteger.startsWith(".") && possibleInteger.matches("\.[0-9]*")) {
        if (possibleInteger.matches("\.[0]*")) {
            System.out.println("The possibleInteger=" + possibleInteger + " is an integer because it starts with a decimal point and afterwards is all zeros.");
            return true;
        } else {
            System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it starts with a decimal point and afterwards is not all zeros.");
            return false;
        }
    } else if (possibleInteger.endsWith(".")  && possibleInteger.matches("[0-9]*\.")) {
        System.out.println("The possibleInteger="+possibleInteger+" is an impure integer (ends with decimal point).");
        return true;
    } else if (possibleInteger.contains(".")) {
        String[] partsOfPossibleInteger = possibleInteger.split("\.");
        if (partsOfPossibleInteger.length == 2) {
            //System.out.println("The possibleInteger=" + possibleInteger + " is split into '" + partsOfPossibleInteger[0] + "' and '" + partsOfPossibleInteger[1] + "'.");
            if (partsOfPossibleInteger[0].matches("[0-9]*")) {
                if (partsOfPossibleInteger[1].matches("[0]*")) {
                    System.out.println("The possibleInteger="+possibleInteger+" is an impure integer (ends with all zeros after the decimal point).");
                    return true;
                } else if (partsOfPossibleInteger[1].matches("[0-9]*")) {
                    System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the numbers after the decimal point (" + 
                                partsOfPossibleInteger[1] + ") are not all zeros.");
                    return false;
                } else {
                    System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the 'numbers' after the decimal point (" + 
                            partsOfPossibleInteger[1] + ") are not all numeric digits.");
                    return false;
                }
            } else {
                System.out.println("The possibleInteger=" + possibleInteger + " is NOT an integer because it the 'number' before the decimal point (" + 
                        partsOfPossibleInteger[0] + ") is not a number.");
                return false;
            }
        } else {
            System.out.println("The possibleInteger="+possibleInteger+" is NOT an integer because it has a strange number of decimal-period separated parts (" +
                    partsOfPossibleInteger.length + ").");
            return false;
        }
    } // else
    System.out.println("The possibleInteger='"+possibleInteger+"' is NOT an integer, even though it has no decimal point.");
    return false;
}
}


测试代码:

String[] testData = {"0", "0.", "0.0", ".000", "2", "2.", "2.0", "2.0000", "3.14159", ".0001", ".", ".0", "3E24", "6.0221409e+23"};
int i = 0;
for (String possibleInteger : testData ) {
    System.out.println("");
    System.out.println(i + ". possibleInteger='" + possibleInteger +"' isIntegerFromDecimalString=" + isIntegerFromDecimalString(possibleInteger));
    i++;
}


评论


我认为您的解释揭示了人们实际上不会想到的情况,并将允许使用更强大的代码。但是,您假设我们对定界符使用句点(。)。它不包括输入的可读性,例如:千位分隔符,会计括号,其他基数或我们使用阿拉伯数字。也没有理由在此方法中引发异常,因为我们知道该字符串在不可变状态下应处于每种状态,并且我们将成为优秀的程序员并修改引用-进一步阅读wiki.c2.com/?ExceptionPatterns

–大卫·费舍尔
19年11月21日在11:30



大卫-你是绝对正确的;特别是关于逗号分隔符(这对于可读性很重要)。对于真正的通用解决方案,我们需要考虑所有假设-尽管我可以肯定的是,没有太多人使用非阿拉伯数字。 :-)

–蒂哈默(Tihamer)
19年11月22日在14:06

#30 楼

我不喜欢使用正则表达式的方法,因为正则表达式无法检查范围(Integer.MIN_VALUEInteger.MAX_VALUE)。

如果您期望在大多数情况下使用int值,而int并不罕见,那么我建议使用Integer.valueOfInteger.parseInt捕捉到NumberFormatException。这种方法的优势-您的代码具有良好的可读性:

public static boolean isInt(String s) {
  try {
    Integer.parseInt(s);
    return true;
  } catch (NumberFormatException nfe) {
    return false;
  }
}


如果您需要检查String是否为整数,并关心性能,那么最好的方法是使用java jdk Integer.parseInt的实现,但修改很少(用return false替换抛出):

此函数具有良好的性能和保证正确的结果:

   public static boolean isInt(String s) {
    int radix = 10;

    if (s == null) {
        return false;
    }

    if (radix < Character.MIN_RADIX) {
        return false;
    }

    if (radix > Character.MAX_RADIX) {
        return false;
    }

    int result = 0;
    boolean negative = false;
    int i = 0, len = s.length();
    int limit = -Integer.MAX_VALUE;
    int multmin;
    int digit;

    if (len > 0) {
        char firstChar = s.charAt(0);
        if (firstChar < '0') { // Possible leading "+" or "-"
            if (firstChar == '-') {
                negative = true;
                limit = Integer.MIN_VALUE;
            } else if (firstChar != '+')
                return false;

            if (len == 1) // Cannot have lone "+" or "-"
                return false;
            i++;
        }
        multmin = limit / radix;
        while (i < len) {
            // Accumulating negatively avoids surprises near MAX_VALUE
            digit = Character.digit(s.charAt(i++), radix);
            if (digit < 0) {
                return false;
            }
            if (result < multmin) {
                return false;
            }
            result *= radix;
            if (result < limit + digit) {
                return false;
            }
            result -= digit;
        }
    } else {
        return false;
    }
    return true;
}