I did it, but this approach seems to me to be wrong:

private static boolean isDigit(String s) throws NumberFormatException { try { Integer.parseInt(s); return true; } catch (NumberFormatException e) { return false; } } 
  • 2
    Only NumberFormatException this function never seems to throw. - ivkremer
  • one
    @Kremchik why does it work correctly for me? - Pavel
  • 2
    It works for me too. I'm just talking about the throws declaration NumberFormatException - in my opinion it is unnecessary, because This exception to the function will never crash. - ivkremer
  • one
    You can also trim () to trim the spaces at the beginning and at the end (if this is not important, of course). Regarding the name of the function - I agree with @Kremchik - skegg
  • one
    Here the main choice of the proposed options - the choice of speed. Make a test program, run this function in different ways many, many times and analyze the program execution time. - skegg

8 answers 8

I understand that the goal is to check Integer ? Then you can:

 s.matches("[-+]?\\d+") // для списка ΠΈΠ· 1 ΠΌΠ»Π½ Ρ†Π΅Π»Ρ‹Ρ… чисСл ΠΈ Π½Π΅ чисСл // (ΠΏΡ€ΠΈΠΌΠ΅Ρ€Π½ΠΎ 50/50) ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ этой строчки практичСски // Π½Π΅ отличаСтся ΠΎΡ‚ описанной Π² вопросС Ρ„ΡƒΠ½ΠΊΡ†ΠΈΠΈ. 

If double , but without exponential notation, then

 ((-|\\+)?[0-9]+(\\.[0-9]+)?)+ 

such a regular fit.

Although I would not steamed and would do the same, only with Double.parseDouble(s) , but I'm not an indicator :) And I also paid attention to the name of the method - it is not very correct, because first, there is one in the Character class, and second, the meaning isNumeric() . But these are just comments from the "what I think about this."

There is a very good static method in commons-lang (the NumberUtils class) that takes into account the many features of Java numbers:

 /** * <p>Checks whether the String a valid Java number.</p> * * <p>Valid numbers include hexadecimal marked with the <code>0x</code> * qualifier, scientific notation and numbers marked with a type * qualifier (eg 123L).</p> * * <p><code>Null</code> and empty String will return * <code>false</code>.</p> * * @param str the <code>String</code> to check * @return <code>true</code> if the string is a correctly formatted number */ public static boolean isNumber(String str) 

    The method described in the question is the most correct method.

    Methods that check whether a string consists only of numbers will not cope with the overflow (try the number 100000000000000000000000000000000 ). The correct pattern for an integer is :

      ^(-?([1-9][0-9]{0,8} |1[0-9]{9} |20[0-9]{8} |21[0-3][0-9]{7} |214[0-6][0-9]{6} |2147[0-3][0-9]{5} |21474[0-7][0-9]{4} |214748[0-2][0-9]{3} |2147483[0-5][0-9]{2} |21474836[0-3][0-9]{1} |214748364[0-7] ) |-2147483648 |0)$ 

    and believe you don’t want to debug it or adapt it for other types.

    In this case, decisions based on patterns will not take into account the locale and the allowed bit delimiters . So try to parse and catch an exception - almost the only correct solution.

    • habrahabr.ru/post/234193 - Qwertiy ♦
    • @Qwertiy: Well, there are some bugs and where. To write curves bicycles to the bugs of a separate version of a separate platform is wrong. - VladD
    • Using exceptions for standard logic is wrong :) - Qwertiy ♦
    • @Qwertiy: Yes, it is for this that this method is needed - to cast a hole in the platform design. In .NET, for example, there is an honest int.TryParse . - VladD
    • @Qwertiy: But essentially creating two separate int 'a parsers and praying to Gosling to be consistent is very wrong. The logic for parsing an int from a string should only be in one place, and this place is Integer.parseInt . - VladD

    As long as your regular expression is compiled ...

     public boolean isNumber(String str) { if (str == null || str.isEmpty()) return false; for (int i = 0; i < str.length(); i++) { if (!Character.isDigit(str.charAt(i))) return false; } return true; } 

      If you write under , then you can use android.text.TextUtils :

       boolean isDigits = TextUtils.isDidgistOnly("123"); 
      • where to get the TextUtils class? - Nofate ♦
      • @Nofate, this is an android class. Completed the answer. - Yuriy SPb ♦

      In connection with the increased interest on this issue, I did a little research :)

      The full code is available here .

      The study involved classes:

       CharacterDelegator() // ΠΊΠΎΠ΄ @Sergey ComplexMatcher() // ΠΊΠΎΠ΄ @VladD NumberUtilsDelegator() // ΠΌΠΎΠΉ ΠΊΠΎΠ΄ SimpleMatcher() // ΠΊΠΎΠ΄ @ivkremer (для простых чисСл) GuavaDelegator() // ΠΊΠΎΠ΄ @Nofate♦ SimpleMatcherWithDot() // ΠΊΠΎΠ΄ @ivkremer (для чисСл с Ρ‚ΠΎΡ‡ΠΊΠΎΠΉ) SimpleParser() // ΠΎΡ€ΠΈΠ³ΠΈΠ½Π°Π»ΡŒΠ½Ρ‹ΠΉ ΠΊΠΎΠ΄ ΠΎΡ‚ @pol GuavaComplexDelegator() // ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π½Π½Ρ‹ΠΉ Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ ΠΊΠΎΠ΄Π° @Nofate♦ для Float InnerSetImpl() // ΠΌΠΎΠΉ спСцифичСский Π²Π°Ρ€ΠΈΠ°Π½Ρ‚ 

      (@VladD, I apologize, I understand what your regexp is doing, but I could not get it)

      Test data:

       {"1", "1.1", "1.11", "1.0", "-1", "-1.0", "-1.1", "4563575687468353456", "1l", "1L", "1f", "1F", "0xCAFEBABE", "1F", "10000000000000000000000000000000000000000000000000", "1.26767E108"} 

      There is a lot of output, so in short:

      • Absolutely all the lines from the example parsed only NumberUtils (commons-lang)
      • the version with the use of Guava (advanced) coped with everything except long-notations ("l") and "0xCAFEBABE" :) (honestly, I do not understand why he chewed the options with the "f" -notation)
      • the remaining options are mostly designed for parsing the ints, although there is not a word in the original question :)

      But the most interesting is the time of this code.

      Start performance test for core.impl.CharacterDelegator Ints: 125ms Numbers: 67ms Numbers with 25% errors: 50ms Small Ints: 43ms

      Start performance test for core.impl.ComplexMatcher Ints: 10825ms Numbers: 11134ms Numbers with 25% errors: 10606ms Small Ints: 10380ms

      Start performance test for core.impl.InnerSetImpl Ints: 50ms Numbers: 52ms Numbers with 25% errors: 54ms Small Ints: 42ms

      Start performance test for core.impl.NumberUtilsDelegator Ints: 111ms Numbers: 91ms Numbers with 25% errors: 99ms Small Ints: 51ms

      Start performance test for core.impl.SimpleMatcher Ints: 1072ms Numbers: 853ms Numbers with 25% errors: 847ms Small Ints: 766ms

      Start performance test for core.impl.GuavaDelegator Ints: 131ms Numbers: 108ms Numbers with 25% errors: 124ms Small Ints: 119ms

      Start performance test for core.impl.SimpleMatcherWithDot Ints: 3069ms Numbers: 5855ms Numbers with 25% errors: 5484ms Small Ints: 2548ms

      Start performance test for core.impl.SimpleParser Ints: 157ms Numbers: 2189ms Numbers with 25% errors: 2117ms Small Ints: 81ms

      Start performance test for core.impl.GuavaComplexDelegator Ints: 980ms Numbers: 943ms Numbers with 25% errors: 1016ms Small Ints: 837ms

      The test is constructed as follows.

      1. We generate 2 random lists with strings (numbers). There are 4 options:

          1. ΠŸΡ€ΠΎΡΡ‚ΠΎ Π˜Π½Ρ‚Ρ‹. 2. Числа (с 50% Π²Π΅Ρ€ΠΎΡΡ‚Π½ΠΎΡΡ‚ΡŒΡŽ Π² стрингС Π΅ΡΡ‚ΡŒ Ρ‚ΠΎΡ‡ΠΊΠ°). 3. Числа с Π²ΠΎΠ·ΠΌΠΎΠΆΠ½ΠΎΠΉ ошибкой (25% Ρ‡Ρ‚ΠΎ Π² строкС Π΅ΡΡ‚ΡŒ подстрока "error"). 4. Набор Π˜Π½Ρ‚ΠΎΠ² Π² нСбольшом Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π΅. 
      2. We make a test run on 10_000 elements.

      3. Making the run on 1_000_000 items.

      From the above calculations, you can see that NumberUtils is the fastest. Similar time of work at simple options of Guava `and simple regexp. Even adding a simple dot slows down the code considerably. I also note that the @Sergey code works very quickly, but it is designed to check strictly ints.

      And there is my specific example InnerSetImpl . It is based on the assumption that we have a limited number of possible options (that is, we can and are ready to keep them in memory). Then we just put them in the HashSet and check for the presence of lines in it. Actually, this option is the fastest, but the assumption spoils a lot :)

      TOTAL: if you need a simple and elegant solution, then it is best to use NumberUtils.isNumber(str) and not to bathe.

      And if suddenly you have a specific task for parsing not just numbers, but numbers in Java notations, then this is the only fully working version.

      (All of the above applies only to the above code. I do not exclude that it is possible to come up with (or even exist) a more correct or faster solution).

        If the project already uses Google Guava, then you can take from there Ints.tryParse()

        The method checks whether the string consists solely of ASCII digits and an optional sign - ( + does not work, unlike the native Integer.parse() ) and tries to match to a number. In case of failure, returns null :

         Integer a = Ints.tryParse("42ΠΆ"); // null Integer b = Ints.tryParse("42"); // 42 Integer c = Ints.tryParse("+1"); // null 
        • And Guava in the locale can? - VladD
        • @VladD, but for integers in principle? - Nofate ♦
        • Well, in theory, yes. For example, Thai numbers or thousands separators . - VladD
        • @VladD, "exclusively from ASCII digits" - Nofate ♦
        • Hint understood :-) - VladD

        To check double numbers

         private static boolean numeralOrNot(String str) { if (str == null || str.isEmpty()) { return false; } int commaCount = 0; for (int i = 0; i < str.length(); i++) { if (str.charAt(i) == '.') { commaCount++; } if ((!Character.isDigit(str.charAt(i)) && str.charAt(i) != '.' && str.charAt(i) != '-') || commaCount > 1) { return false; } } return true; }