什么是最好的方法来检查一个字符串是否代表Java中的整数?

我通常使用下面的成语来检查一个字符串是否可以转换为一个整数。

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

这只是我,还是这似乎有点hackish? 什么是更好的方法?


看到我的答案(基于CodingWithSpike的早期答案 ),看看我为什么扭转了我的立场,接受了Jonas Klemming对这个问题的答案 。 我认为这个原始的代码将被大多数人使用,因为它的实现更快,更易于维护,但是当提供非整数数据时,它的速度要慢几个数量级。

如果你不关心潜在的溢出问题,这个函数比使用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; } 

你有它,但你应该只捕获NumberFormatException

做了一个快速的基准。 除非你开始弹出多个方法,并且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的解决方案也是最强大的。 看起来他赢了:)

由于有可能人们仍然在这里访问,并会在基准测试之后对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 
 org.apache.commons.lang.StringUtils.isNumeric 

尽管Java的标准库真的错过了这样的实用功能

我认为Apache Commons是每个Java程序员都必须拥有的

太糟糕了,它尚未移植到Java5

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

如果你的意思是“可以在Java中转换为int”,那么Jonas的回答是一个好的开始,但是并没有完成这个工作。 例如,它会通过999999999999999999999999999999。 我会在方法的末尾添加正常的try / catch调用。

逐个字符的检查将有效地拒绝“不是一个整数”的情况,留下“这是一个整数,但Java无法处理”的情况下被较慢的异常路由捕获。 你也可以手动做这个,但是会更复杂。

只是一个正则表达式的评论。 这里提供的每个例子都是错误的! 如果你想使用正则表达式不要忘记编译模式需要花费很多时间。 这个:

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

我从rally25rs的答案复制了代码,并添加了一些非整数数据的测试。 结果无可否认地赞成Jonas Klemming所发表的方法。 我最初发布的异常方法的结果对于整数数据来说是相当不错的,但是如果不这样做的话,结果是最差的,而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 

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

这个更短,但是更短不一定更好( 如danatel的评论中所指出的 ,它不会捕获超出范围的整数值):

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

就个人而言,因为实施是在一个帮助方法松鼠,正确性胜过长度,我只是像你有什么东西(减去捕获基本的Exception类而不是NumberFormatException )。

有番石榴版本:

 import com.google.common.primitives.Ints; Integer intValue = Ints.tryParse(stringValue); 

它将返回null,而不是在解析字符串失败时抛出异常。

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

如果您的字符串数组包含纯整数和字符串,下面的代码应该工作。 你只需要看第一个字符。 例如[“4”,“44”,“abc”,“77”,“bond”]

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

怎么样:

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

您可能也需要考虑用例:

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

你只要检查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 } 

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

这是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 
 is_number = true; try { Integer.parseInt(mystr) } catch (NumberFormatException e) { is_number = false; } 

你做的工作,但你可能不应该总是检查这种方式。 投掷异常应该保留用于“特殊”情况(可能适合您的情况),并且在性能方面成本非常高。

 Number number; try { number = NumberFormat.getInstance().parse("123"); } catch (ParseException e) { //not a number - do recovery. e.printStackTrace(); } //use number 

这只适用于正整数。

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

你可以试试apache utils

 NumberUtils.isNumber( myText) 

在这里看到javadoc

这对我有用。 简单来确定一个字符串是一个原始的还是一个数字。

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

要检查所有的诠释字符,你可以简单地使用双重否定。

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

[^ 0-9] + $检查是否有任何字符不是整数,所以测试失败,如果是真的。 只是不这样做,你会成功。

找到这可能有帮助:

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

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

 TextUtils.isDigitsOnly(str); 

我相信没有任何风险会碰到一个异常,因为正如你在下面看到的,你总是安全地将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是一个float还是double但在这种情况下你只能遇到一个。 (点),当然检查digits == (aString.length()-1)

同样,这里的解析异常也没有风险,但是如果你打算解析一个包含数字的字符串(比如说int数据类型),你必须首先检查它是否适合数据类型。 否则,你必须投它。

我希望我帮助

 public class HelloWorld{ static boolean validateIP(String s){ String[] value = s.split("\\."); if(value.length!=4) return false; int[] v = new int[4]; for(int i=0;i<4;i++){ for(int j=0;j<value[i].length();j++){ if(!Character.isDigit(value[i].charAt(j))) return false; } v[i]=Integer.parseInt(value[i]); if(!(v[i]>=0 && v[i]<=255)) return false; } return true; } public static void main(String[] argv){ String test = "12.23.8.9j"; if(validateIP(test)){ System.out.println(""+test); } } } 

我在这里看到了很多答案,但是他们中的大多数能够确定字符串是否是数字,但是它们检查数字是否在整数范围内失败。

所以我的目的是这样的:

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