Apa cara terbaik untuk memeriksa apakah suatu String merepresentasikan integer di Java?


214

Saya biasanya menggunakan idiom berikut untuk memeriksa apakah sebuah String dapat dikonversi ke integer.

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

Apakah hanya saya, atau apakah ini terlihat agak merdu? Apa cara yang lebih baik?


Lihat jawaban saya (dengan tolok ukur, berdasarkan jawaban sebelumnya oleh CodingWithSpike ) untuk melihat mengapa saya membalik posisi saya dan menerima jawaban Jonas Klemming untuk masalah ini. Saya pikir kode asli ini akan digunakan oleh kebanyakan orang karena lebih cepat untuk diimplementasikan, dan lebih dapat dipelihara, tetapi urutan besarnya lebih lambat ketika data non-integer disediakan.


Apa ide Anda tentang RegExp untuk solusinya?
Akshay Pethani

Jawaban:


171

Jika Anda tidak khawatir dengan potensi masalah luapan, fungsi ini akan melakukan sekitar 20-30 kali lebih cepat daripada menggunakan 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> = ':') terlihat agak aneh. Saya akan menggunakan (c <'0' || c> '9') ... apakah <= dan> = operator lebih cepat di Java?
Anonim

3
Mengapa tidak menggunakan regex? Bukankah mengembalikan str.matches ("^ -? \\ d + $") identik dengan kode di atas.
Maglob

15
Saya akan menggunakan metode ini atau metode asli dari pertanyaan sebelum regex. Ini untuk kinerja, metode asli untuk kecepatan implementasi dan pemeliharaan yang murni. Solusi regex tidak ada artinya.
Bill the Lizard

4
Saya khawatir overflow, tetapi metode ini dapat diadaptasi untuk BigInts dan masih jauh lebih cepat daripada metode lain. Jika ada orang yang bertanya-tanya mengapa saya melakukan begitu banyak masalah sederhana, saya membuat perpustakaan untuk membantu memecahkan masalah Project Euler.
Bill the Lizard

1
Jika Anda khawatir apakah Anda benar-benar dapat mengurai string menjadi int atau panjang Anda juga perlu memeriksa apakah integer yang diwakili string tersebut benar-benar cocok dengan tipe data tersebut.
Jonas K

65

Anda memilikinya, tetapi Anda seharusnya hanya menangkap NumberFormatException.


7
Ya, itu dianggap bentuk yang buruk untuk menangkap lebih banyak pengecualian dari yang Anda butuhkan.
Chris

Kamu benar. NFE adalah satu-satunya yang bisa dibuang, tetapi masih merupakan kebiasaan buruk untuk masuk.
Bill the Lizard

Saya pikir NPE dapat dilemparkan jika inputnya nol, jadi metode Anda mungkin harus menangani itu secara eksplisit, dengan cara apa pun yang Anda inginkan.
Dov Wasserman

@Dov: Anda NPE dan NFE yang benar harus keduanya ditangkap secara eksplisit.
Bill the Lizard

Respons ini harus menjadi jawaban yang benar untuk pertanyaan ini.
Breedly

40

Melakukan patokan cepat. Pengecualian sebenarnya tidak terlalu mahal, kecuali jika Anda mulai membuka kembali banyak metode dan JVM harus melakukan banyak pekerjaan untuk mendapatkan tumpukan eksekusi di tempat. Ketika tetap menggunakan metode yang sama, mereka bukan berkinerja buruk.

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

Keluaran:

ByException: 31

ByRegex: 453 (catatan: mengkompilasi ulang pola setiap waktu)

ByJonas: 16

Saya setuju bahwa solusi Jonas K adalah yang paling kuat juga. Sepertinya dia menang :)


13
Ide bagus untuk benchmark ketiganya. Agar adil dengan metode Regex dan Jonas, Anda harus menguji dengan string non-integer, karena di situlah metode Integer.parseInt akan benar-benar melambat.
Bill the Lizard

4
Maaf tapi tes regex ini tidak bagus. (1) Anda tidak perlu membuat cek mesin regex untuk ^dan $kedua kalinya sejak di matchesseluruh string harus sesuai regex, (2) str.matchessetiap kali akan harus membuat sendiri Patternyang mahal. Untuk alasan kinerja, kita harus membuat Pola seperti itu hanya sekali di luar metode ini dan menggunakannya di dalam. (3) Kami juga dapat membuat hanya satu objek Pencocokan dan menggunakannya reset(CharSequence)untuk meneruskan data pengguna dan mengembalikan matches()hasilnya.
Pshemo

Jadi sesuatu seperti private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }harus memiliki kinerja yang lebih baik.
Pshemo

@Pshemo Integer.valueOf ("1") dan Integer.valueOf ("1") sama-sama melempar pengecualian sehingga memeriksa ^ dan $ tampak masuk akal.
cquezel

1
@cquezel Ya, tetapi tidak diharuskan karena matchesditambahkan ^dan $secara implisit. Lihatlah hasil " 123".matches("\\d+")dan "123".matches("\\d+"). Anda akan melihat falsedan true. falseakan dikembalikan karena string dimulai dengan ruang yang mencegahnya tidak sepenuhnya cocok dengan regex.
Pshemo

37

Karena ada kemungkinan orang masih berkunjung ke sini dan akan bias terhadap Regex setelah tolok ukur ... Jadi saya akan memberikan versi terbaru dari tolok ukur, dengan versi kompilasi dari Regex. Yang bertentangan dengan tolok ukur sebelumnya, yang satu ini menunjukkan solusi Regex sebenarnya memiliki kinerja yang baik secara konsisten.

Disalin dari Bill the Lizard dan diperbarui dengan versi kompilasi:

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

Hasil:

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
Waktu ByCompiledRegex perlu menyertakan kompilasi regex dalam pengukuran waktunya.
Martin Carney

2
@ MartinCarney Saya memodifikasinya dan kompilasi pola benchmark. Jelas CPU / JIT saya lebih cepat, tetapi jika saya interpolasi kembali, waktu kompilasi adalah 336.
tedder42

2
untuk menjadi jelas, bahwa 336 (ms) adalah apa yang terjadi ketika kompilasi pola dilakukan 100k kali, sama seperti semua baris lainnya. Dengan implikasi bahwa itu hanya dilakukan sekali, waktunya pada dasarnya nol.
tedder42

Terima kasih telah meluruskan catatan pada waktu regex yang dikompilasi.
Lars

Mungkin "^[+-]?\\d+$" akan lebih baik.
Adam

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

meskipun lib standar Java benar-benar melewatkan fungsi utilitas tersebut

Saya pikir Apache Commons adalah "harus memiliki" untuk setiap programmer Java

Sayang sekali itu belum porting ke Java5


1
Satu-satunya masalah dengan ini adalah overflow: SI masih memberi Anda +1 untuk menyebutkan commons-lang :)
javamonkey79

2
Masalah lainnya adalah angka negatif, tetapi saya juga +1, karena menurut saya pendekatan ini paling dekat dengan solusi yang baik.
sandris

23

Sebagian tergantung pada apa yang Anda maksud dengan "dapat dikonversi ke integer".

Jika maksud Anda "dapat dikonversi menjadi int di Jawa" maka jawaban dari Jonas adalah awal yang baik, tetapi tidak cukup menyelesaikan pekerjaan. Itu akan melewati 999999999999999999999999999999 misalnya. Saya akan menambahkan panggilan try / catch normal dari pertanyaan Anda sendiri di akhir metode.

Pemeriksaan karakter-per-karakter akan secara efisien menolak kasus "bukan bilangan bulat", meninggalkan kasus "bilangan bulat tetapi Java tidak dapat mengatasinya" untuk ditangkap oleh rute pengecualian yang lebih lambat. Anda bisa melakukannya sedikit dengan tangan juga, tetapi itu akan jauh lebih rumit.


17

Hanya satu komentar tentang regexp. Setiap contoh yang diberikan di sini salah !. Jika Anda ingin menggunakan regexp jangan lupa bahwa mengompilasi polanya membutuhkan banyak waktu. Ini:

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

dan juga ini:

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

menyebabkan kompilasi pola dalam setiap pemanggilan metode. Untuk menggunakannya dengan benar ikuti:

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
Anda dapat memeras sedikit lebih banyak kinerja dengan membuat Matcher sebelumnya, dan menggunakan metode reset () untuk menerapkannya pada input.
Alan Moore

13

Ada versi jambu biji:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Ini akan mengembalikan nol alih-alih melempar pengecualian jika gagal mengurai string.


3
IMHO jawaban terbaik. Gunakan perpustakaan yang teruji dengan baik alih-alih menggulung solusi Anda sendiri. (Juga lihat diskusi di sini .)
Olivier Cailloux

12

Saya menyalin kode dari jawaban rally25rs dan menambahkan beberapa tes untuk data non-integer. Hasilnya tidak dapat disangkal mendukung metode yang diposting oleh Jonas Klemming. Hasil untuk metode Pengecualian yang awalnya saya posting cukup baik ketika Anda memiliki data integer, tetapi mereka yang terburuk ketika Anda tidak, sedangkan hasil untuk solusi RegEx (yang saya yakinkan banyak orang akan menggunakan) secara konsisten buruk. Lihat jawaban Felipe untuk contoh regex yang dikompilasi, yang jauh lebih cepat.

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

Hasil:

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

Ini lebih pendek, tetapi lebih pendek tidak selalu lebih baik (dan itu tidak akan menangkap nilai integer yang berada di luar jangkauan, seperti yang ditunjukkan dalam komentar danatel ):

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

Secara pribadi, karena implementasi disemprotkan dalam metode helper dan panjang truf kebenaran, saya hanya akan pergi dengan sesuatu seperti apa yang Anda miliki (dikurangi menangkap Exceptionkelas dasar daripada NumberFormatException).


1
Dan mungkin \\ d {1,10} adalah, meskipun tidak sempurna, lebih baik daripada \\ d + untuk menangkap Java
Integers

6

Anda dapat menggunakan metode kecocokan dari kelas string. Tanda [0-9] mewakili semua nilai yang ada, + berarti panjangnya setidaknya satu karakter, dan * berarti panjangnya bisa nol atau lebih karakter.

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 doest ini tidak cocok dengan "+10" atau "-10"), yang biasanya dimasukkan sebagai bilangan bulat yang valid
Tim Wintle

4

Bagaimana tentang:

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

Bagaimana dengan bilangan bulat 9999999999999999999999999999999999?
danatel

Jangan lupa untuk memeriksa tanda negatifnya.
Jeremy Ruten

tidakkah Anda perlu mengaitkan awal dan akhir regex, sehingga Anda tidak akan lulus "aaa-1999zzz"?
Tim Howland

2
Tim, ketika Anda memanggil salah satu dari metode cocok () (String, Pola, dan Matcher masing-masing memilikinya), regex harus mencocokkan seluruh input, membuat jangkar menjadi berlebihan. Untuk menemukan kecocokan yang ditentukan oleh sebagian besar rasa regex lainnya, Anda harus menggunakan Pencocokan # find ().
Alan Moore

4

Ini adalah variasi Java 8 dari jawaban Jonas Klemming:

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

Kode uji:

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

Hasil dari kode tes:

        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

Anda cukup memeriksa 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

Jika array String Anda berisi Integer dan Strings murni, kode di bawah ini akan berfungsi. Anda hanya perlu melihat karakter pertama. mis. ["4", "44", "abc", "77", "bond"]

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

3

Anda juga dapat menggunakan kelas Pemindai , dan menggunakan hasNextInt () - dan ini memungkinkan Anda untuk menguji tipe lainnya, seperti float, dll.


Jawaban ini memberi saya pengingat yang saya butuhkan. Saya benar-benar lupa Scanner memiliki fungsi seperti itu. T-up
Hubro

2

Jika Anda ingin memeriksa apakah string mewakili bilangan bulat yang cocok dengan tipe int, saya melakukan sedikit modifikasi pada jawaban jonas, sehingga string yang mewakili bilangan bulat lebih besar dari Integer.MAX_VALUE atau lebih kecil dari Integer.MIN_VALUE, sekarang akan kembali Salah. Misalnya: "3147483647" akan mengembalikan false karena 3147483647 lebih besar dari 2147483647, dan juga, "-2147483649" juga akan kembali palsu karena -2147483649 lebih kecil dari -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
dapatkah Anda mengedit jawaban Anda dan menjelaskan bagaimana cara meningkatkan jawaban sebelumnya yang Anda sebutkan?
Gilles Gouaillardet

Terima kasih atas jawabannya. Tapi "123" yaitu, 123 bersama dengan ruang dianggap sebagai bilangan bulat yang valid.
Saikrishna Radarapu

1
@SaikrishnaRadarapu Mereka menggunakannya trim()sehingga jelas merupakan pilihan desain yang disengaja.
Guildenstern


1

Anda mungkin perlu mempertimbangkan juga use case di akun:

Jika sebagian besar waktu Anda mengharapkan angka valid, maka menangkap pengecualian hanya menyebabkan overhead kinerja ketika mencoba mengkonversi angka yang tidak valid. Sedangkan memanggil beberapa isInteger()metode dan kemudian mengonversi menggunakan Integer.parseInt()akan selalu menyebabkan overhead kinerja untuk angka yang valid - string diurai dua kali, sekali oleh cek dan sekali oleh konversi.


1

Ini adalah modifikasi dari kode Jonas yang memeriksa apakah string dalam jangkauan untuk dilemparkan ke dalam integer.

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
terlihat bagus, tetapi untuk-loop terakhir harus saya reset ke nol (atau 1 jika angka negatif) karena loop yang memeriksa apakah setiap digit angka akan menghasilkan saya menjadi panjang string, oleh karena itu untuk-loop terakhir tidak akan pernah lari. Saya juga akan menggunakan konstanta Java Integer.MAX_VALUE dan Integer.MIN_VALUE alih-alih angka ajaib.
Tim the Enchanter

@TimtheEnchanter Terima kasih atas sarannya, saya benar-benar mengabaikannya. Dalam edit saya untuk memasukkan mereka, saya menggunakan variabel baru di loop pertama untuk menghindari pernyataan if ekstra.
Wayne

1

Jika Anda menggunakan Android API Anda dapat menggunakan:

TextUtils.isDigitsOnly(str);

1

Pilihan lain:

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
Ini melakukan hal yang persis sama dengan yang ditanyakan oleh poster itu.
Martin Carney

0

Apa yang Anda lakukan berhasil, tetapi Anda mungkin tidak harus selalu memeriksa seperti itu. Melempar pengecualian harus disediakan untuk situasi "luar biasa" (mungkin cocok untuk kasus Anda), dan sangat mahal dalam hal kinerja.


Mereka hanya mahal jika mereka dibuang.
Bill the Lizard

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

0

Ini hanya akan berfungsi untuk bilangan bulat positif.

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
Selamat datang di stackoverflow. Sebelum menghidupkan kembali utas lama pastikan untuk membaca tanggapan dan komentar sebelumnya. Metode ini (dan kemungkinan kerugian) sebenarnya sudah dibahas.
Leigh

0

Ini bekerja untuk saya. Cukup untuk mengidentifikasi apakah suatu String adalah primitif atau angka.

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

Untuk memeriksa semua karakter int, Anda cukup menggunakan negatif ganda.

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

[^ 0-9] + $ memeriksa untuk melihat apakah ada karakter yang tidak bilangan bulat, jadi tes gagal jika itu benar. Hanya BUKAN itu dan Anda menjadi kenyataan pada kesuksesan.


Tidak. Anda jelas belum menguji ini. Ini hanya mengembalikan true jika ada digit di suatu tempat di string, bukan jika string hanya digit. The matchesMetode pertandingan melawan seluruh string, bukan hanya sebagian darinya.
Dawood ibn Kareem

Anda tidak mendapatkan bagian negatif ganda.
Roger F. Gay

Yah, saya TIDAK TIDAK mendapatkan double negative. Ini tidak berhasil. Jika Anda memiliki campuran angka dan huruf, ini masuk ke ifblok. Seharusnya tidak.
Dawood ibn Kareem

0

Temukan ini mungkin membantu:

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

0

Saya percaya tidak ada risiko yang menimpa pengecualian, karena seperti yang Anda lihat di bawah ini, Anda selalu aman intuntuk parsing Stringdan bukan sebaliknya.

Begitu:

  1. Anda memeriksa apakah setiap slot karakter di string Anda cocok dengan setidaknya satu karakter {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. Anda menjumlahkan semua waktu yang Anda temui di slot karakter di atas.

    digits++;
  3. Dan akhirnya Anda memeriksa apakah waktu yang Anda temui integer sebagai karakter sama dengan panjang string yang diberikan.

    if(digits == aString.length())

Dan dalam praktiknya kita memiliki:

    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!!");
    }

Dan hasilnya adalah:

Ini bilangan bulat !!

Itu bukan bilangan bulat !!

Demikian pula, Anda dapat memvalidasi jika a Stringadalah a floatatau a doubletetapi dalam kasus-kasus tersebut Anda hanya perlu menjumpai satu. (dot) di String dan tentu saja periksa apakah digits == (aString.length()-1)

Sekali lagi, tidak ada risiko menabrak pengecualian parsing di sini, tetapi jika Anda berencana untuk menguraikan string yang diketahui berisi angka (katakanlah tipe data int ), Anda harus terlebih dahulu memeriksa apakah cocok dengan tipe data. Kalau tidak, Anda harus melemparkannya.

Saya harap saya membantu

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.