Cách tốt nhất để kiểm tra xem Chuỗi có đại diện cho một số nguyên trong Java không?


214

Tôi thường sử dụng thành ngữ sau để kiểm tra xem Chuỗi có thể được chuyển đổi thành số nguyên hay không.

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

Có phải chỉ có tôi, hoặc điều này có vẻ hơi hack? Cách nào tốt hơn?


Xem câu trả lời của tôi (với điểm chuẩn, dựa trên câu trả lời trước đó của CodingWithSpike ) để biết lý do tại sao tôi đã đảo ngược vị trí của mình và chấp nhận câu trả lời của Jonas Klemming cho vấn đề này. Tôi nghĩ rằng mã gốc này sẽ được sử dụng bởi hầu hết mọi người bởi vì nó nhanh hơn để thực hiện và dễ bảo trì hơn, nhưng đó là các đơn đặt hàng có cường độ chậm hơn khi dữ liệu không nguyên được cung cấp.


Ý tưởng của bạn về RegExp cho giải pháp là gì?
Akshay Pethani

Câu trả lời:


171

Nếu bạn không quan tâm đến các sự cố tràn tiềm năng, chức năng này sẽ thực hiện nhanh hơn khoảng 20-30 lần so với sử dụng 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> = ':') trông hơi lạ. Tôi đã sử dụng (c <'0' || c> '9') ... các toán tử <= và> = có nhanh hơn trong Java không?
Ẩn danh

3
Tại sao không sử dụng regex? Không trả về str.matches ("^ -? \\ d + $") giống hệt với mã ở trên.
Maglob

15
Tôi sẽ sử dụng phương pháp này hoặc phương pháp ban đầu từ câu hỏi trước regex. Điều này cho hiệu suất, phương pháp ban đầu cho tốc độ thực hiện và khả năng duy trì tuyệt đối. Các giải pháp regex không có gì đi cho nó.
Bill Lizard

4
Tôi lo lắng về việc tràn, nhưng phương pháp này có thể được điều chỉnh cho BigInt và vẫn nhanh hơn các phương thức khác. Trong trường hợp bất cứ ai thắc mắc tại sao tôi lại nỗ lực rất nhiều vào một vấn đề đơn giản như vậy, tôi đang tạo một thư viện để hỗ trợ giải quyết các vấn đề của Project Euler.
Bill Lizard

1
Nếu bạn lo lắng liệu bạn có thực sự phân tích chuỗi thành int hay dài hay không, bạn cũng cần kiểm tra xem số nguyên mà chuỗi đại diện có thực sự phù hợp với các loại dữ liệu đó hay không.
Jonas K

65

Bạn có nó, nhưng bạn chỉ nên bắt NumberFormatException.


7
Vâng, nó được coi là hình thức xấu để bắt nhiều ngoại lệ hơn bạn cần.
Chris

Bạn đúng. NFE là người duy nhất có thể bị ném, nhưng đó vẫn là một thói quen xấu.
Bill Lizard

Tôi nghĩ rằng một NPE có thể được ném nếu đầu vào là null, vì vậy phương thức của bạn có thể nên xử lý rõ ràng, bất cứ cách nào bạn muốn.
Dov Wasserman

@Dov: Cả NPE và NFE đều đúng nên được nắm bắt rõ ràng.
Bill Lizard

Câu trả lời này phải là câu trả lời thực sự cho câu hỏi này.
Nhân giống

40

Đã làm một điểm chuẩn nhanh chóng. Các ngoại lệ không thực sự mở rộng, trừ khi bạn bắt đầu bật lại nhiều phương thức và JVM phải thực hiện rất nhiều công việc để đưa ngăn xếp thực thi vào vị trí. Khi ở cùng một phương pháp, họ không phải là người biểu diễn tồi.

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

Đầu ra:

Ngoại lệ: 31

ByRegex: 453 (lưu ý: biên dịch lại mẫu mỗi lần)

ByJonas: 16

Tôi đồng ý rằng giải pháp của Jonas K cũng mạnh mẽ nhất. Hình như anh ấy thắng :)


13
Ý tưởng tuyệt vời để điểm chuẩn cả ba. Để công bằng với các phương thức Regex và Jonas, bạn nên kiểm tra với các chuỗi không nguyên, vì đó là phương thức Integer.parseInt sẽ thực sự chậm lại.
Bill the Lizard

4
Xin lỗi nhưng bài kiểm tra regex này không tốt. (1) Bạn không cần phải thực hiện kiểm tra công cụ regex ^$lần thứ hai vì trong matchestoàn bộ chuỗi phải khớp với regex, (2) str.matchesmỗi lần sẽ phải tạo một Patterncông cụ đắt tiền. Vì lý do hiệu suất, chúng ta chỉ nên tạo Mẫu như vậy một lần ngoài phương thức này và sử dụng nó bên trong. (3) Chúng tôi cũng chỉ có thể tạo một đối tượng Matcher và sử dụng nó reset(CharSequence)để truyền dữ liệu người dùng và trả về matches()kết quả của nó .
Pshemo

Vì vậy, một cái gì đó như private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }nên có hiệu suất tốt hơn.
Pshemo

@Pshemo Integer.valueOf ("1") và Integer.valueOf ("1") đều ném ngoại lệ để kiểm tra ^ và $ có vẻ hợp lý.
cquezel

1
@cquezel Có, nhưng không bắt buộcphảimatches thêm ^$ngầm. Hãy xem kết quả của " 123".matches("\\d+")"123".matches("\\d+"). Bạn sẽ thấy falsetrue. falsesẽ được trả về vì chuỗi bắt đầu bằng khoảng trắng ngăn không cho nó hoàn toàn khớp với regex.
Pshemo

37

Vì có khả năng mọi người vẫn truy cập vào đây và sẽ bị thiên vị so với Regex sau các điểm chuẩn ... Vì vậy, tôi sẽ đưa ra một phiên bản cập nhật của điểm chuẩn, với phiên bản được biên dịch của Regex. Trái ngược với các điểm chuẩn trước đó, điều này cho thấy giải pháp Regex thực sự có hiệu suất tốt.

Sao chép từ Bill the Lizard và được cập nhật với phiên bản được biên dịch:

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

Các kết quả:

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
Thời gian ByCompiledRegex cần bao gồm biên dịch regex trong phép đo thời gian của nó.
Martin Carney

2
@MartinCarney Tôi đã sửa đổi nó và biên dịch mẫu chuẩn. Rõ ràng CPU / JIT của tôi nhanh hơn, nhưng nếu tôi nội suy nó trở lại, thời gian biên dịch là 336.
tedder42

2
rõ ràng, 336 (ms) là những gì xảy ra khi quá trình biên dịch mẫu được thực hiện 100 nghìn lần, giống như tất cả các dòng khác. Với ngụ ý rằng nó chỉ được thực hiện một lần, thời gian của nó về cơ bản là bằng không.
tedder42

Cảm ơn đã thiết lập bản ghi thẳng vào thời gian regex được biên dịch.
LarsH

Có lẽ "^[+-]?\\d+$"sẽ tốt hơn nữa.
Adam

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

mặc dù lib tiêu chuẩn của Java thực sự bỏ lỡ các hàm tiện ích như vậy

Tôi nghĩ rằng Apache Commons là "phải có" cho mọi lập trình viên Java

quá tệ, nó chưa được chuyển sang Java5


1
Vấn đề duy nhất với điều này là tràn: SI vẫn cho bạn +1 khi đề cập đến commons-lang :)
javamonkey79

2
Vấn đề khác là số âm, nhưng tôi cũng +1, vì theo quan điểm của tôi, cách tiếp cận này gần nhất với một giải pháp tốt.
Sandris

22

Nó một phần phụ thuộc vào ý của bạn bởi "có thể được chuyển đổi thành một số nguyên".

Nếu bạn có nghĩa là "có thể được chuyển đổi thành int trong Java" thì câu trả lời từ Jonas là một khởi đầu tốt, nhưng không hoàn thành công việc. Nó sẽ vượt qua 999999999999999999999999999999. Tôi sẽ thêm cuộc gọi thử / bắt bình thường từ câu hỏi của riêng bạn vào cuối phương thức.

Việc kiểm tra từng ký tự sẽ loại bỏ hiệu quả các trường hợp "không phải là số nguyên", để lại "đó là số nguyên nhưng Java không thể xử lý" các trường hợp bị bắt bởi tuyến ngoại lệ chậm hơn. Bạn cũng có thể làm điều này bằng tay, nhưng nó sẽ phức tạp hơn rất nhiều.


17

Chỉ cần một nhận xét về regrec. Mọi ví dụ được cung cấp ở đây là sai!. Nếu bạn muốn sử dụng regrec, đừng quên rằng việc biên dịch mẫu mất rất nhiều thời gian. Điều này:

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

và cũng thế này:

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

gây ra biên dịch mẫu trong mọi cuộc gọi phương thức. Để sử dụng chính xác, hãy làm theo:

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
Bạn cũng có thể giảm hiệu năng hơn một chút bằng cách tạo Matcher trước thời hạn và sử dụng phương thức reset () của nó để áp dụng nó cho đầu vào.
Alan Moore

13

Có phiên bản ổi:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

Nó sẽ trả về null thay vì ném một ngoại lệ nếu không phân tích được chuỗi.


3
Câu trả lời hay nhất IMHO. Sử dụng các thư viện được thử nghiệm tốt thay vì đưa ra giải pháp của riêng bạn. (Cũng xem cuộc thảo luận ở đây .)
Olivier Cailloux

12

Tôi đã sao chép mã từ câu trả lời biểu tình và thêm một số bài kiểm tra cho dữ liệu không nguyên. Không thể phủ nhận kết quả ủng hộ phương pháp được đăng bởi Jonas Klemming. Kết quả cho phương pháp Ngoại lệ mà tôi đã đăng ban đầu khá tốt khi bạn có dữ liệu số nguyên, nhưng chúng là tồi tệ nhất khi bạn không, trong khi kết quả cho giải pháp RegEx (tôi sẽ đặt cược nhiều người sử dụng) đã liên tục xấu. Xem câu trả lời của Felipe cho một ví dụ regex được biên dịch, nhanh hơn nhiều.

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

Các kết quả:

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

Cái này ngắn hơn, nhưng ngắn hơn không nhất thiết phải tốt hơn (và nó sẽ không bắt được các giá trị nguyên nằm ngoài phạm vi, như được chỉ ra trong nhận xét của danatel ):

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

Cá nhân, vì việc triển khai bị thu hẹp trong một phương thức của người trợ giúp và độ dài chính xác hơn, tôi sẽ chỉ đi với một cái gì đó giống như những gì bạn có (trừ đi bắt Exceptionlớp cơ sở chứ không phải NumberFormatException).


1
Và có lẽ, \ d {1,10}, mặc dù không hoàn hảo, tốt hơn so với \\ d + để bắt các số nguyên Java
Maglob

6

Bạn có thể sử dụng phương thức khớp của lớp chuỗi. [0-9] đại diện cho tất cả các giá trị có thể có, + có nghĩa là nó phải dài ít nhất một ký tự và * có nghĩa là nó có thể dài bằng 0 hoặc nhiều ký tự.

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 điều này không khớp với "+10" hoặc "-10"), thường được bao gồm dưới dạng số nguyên hợp lệ
Tim Wintle

4

Làm thế nào về:

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

Còn số nguyên 9999999999999999999999999999999999 thì sao?
danatel

Đừng quên kiểm tra các dấu hiệu tiêu cực.
Jeremy Ruten

bạn không cần phải bắt đầu và kết thúc regex, vì vậy bạn sẽ không vượt qua "aaa-1999zzz"?
Tim Howland

2
Tim, khi bạn gọi một trong các phương thức Match () (String, Pattern và Matcher đều có một), regex phải khớp với toàn bộ đầu vào, làm cho neo trở nên dư thừa. Để tìm một kết quả theo định nghĩa của hầu hết các hương vị regex khác, bạn phải sử dụng Matcher # find ().
Alan Moore

4

Đây là một biến thể Java 8 của câu trả lời 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)));
}

Mã kiểm tra:

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

Kết quả của mã kiểm tra:

        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

Bạn chỉ cần kiểm tra 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

Nếu mảng Chuỗi của bạn chứa Số nguyên và Chuỗi thuần, mã bên dưới sẽ hoạt động. Bạn chỉ cần nhìn vào nhân vật đầu tiên. ví dụ: "" 4 "," 44 "," abc "," 77 "," trái phiếu "]

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

3

Bạn cũng có thể sử dụng lớp Scanner và sử dụng hasNextInt () - và điều này cho phép bạn kiểm tra các loại khác, như float, v.v.


Câu trả lời này đã cho tôi một lời nhắc nhở tôi cần. Tôi hoàn toàn quên rằng Scanner có chức năng như vậy. T-up
Hubro

2

Nếu bạn muốn kiểm tra xem chuỗi có đại diện cho một số nguyên phù hợp với kiểu int không, tôi đã sửa đổi một chút cho câu trả lời của jonas, để các chuỗi đại diện cho số nguyên lớn hơn Integer.MAX_VALUE hoặc nhỏ hơn Integer.MIN_VALUE, giờ đây sẽ trả về sai. Ví dụ: "3147483647" sẽ trả về false vì 3147483647 lớn hơn 2147483647 và tương tự, "-2147483649" cũng sẽ trả về false vì -2147483649 nhỏ hơn -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
bạn có thể vui lòng chỉnh sửa câu trả lời của bạn và giải thích làm thế nào nó cải thiện câu trả lời trước đó bạn đã đề cập?
Gilles Gouaillardet

Cảm ơn câu trả lời tuyệt vời. Nhưng "123" tức là 123 cùng với không gian được coi là số nguyên hợp lệ.
Saikrishna Radarapu

1
@SaikrishnaRadarapu Họ sử dụng trim()vì vậy đó rõ ràng là một sự lựa chọn thiết kế có chủ ý.
Guildenstern

2

Bạn có thể thử dụng cụ apache

NumberUtils.isCreatable(myText)

Xem javadoc tại đây


1
Có vẻ như phương pháp này không được chấp nhận trong liên kết phát hành mới nhất ). Rõ ràng bạn nên sử dụng isCreateable(String)thay thế.
Guildenstern

Cập nhật. Cảm ơn @Guildenstern
borjab

1

Bạn cũng có thể cần phải sử dụng trường hợp sử dụng trong tài khoản:

Nếu hầu hết thời gian bạn mong đợi các số là hợp lệ, thì việc bắt ngoại lệ chỉ gây ra chi phí hiệu năng khi cố gắng chuyển đổi các số không hợp lệ. Trong khi gọi một số isInteger()phương thức và sau đó chuyển đổi bằng cách sử dụng Integer.parseInt()sẽ luôn gây ra chi phí hiệu năng cho các số hợp lệ - các chuỗi được phân tích cú pháp hai lần, một lần bằng kiểm tra và một lần bằng chuyển đổi.


1

Đây là một sửa đổi mã của Jonas để kiểm tra xem chuỗi có nằm trong phạm vi được truyền thành một số nguyên hay không.

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
Có vẻ tốt, nhưng vòng lặp for cuối cùng cần phải đặt lại về 0 (hoặc 1 nếu là số âm) vì vòng lặp kiểm tra xem mỗi chữ số có phải là một số sẽ dẫn đến i là độ dài chuỗi hay không, do đó vòng lặp for cuối cùng sẽ không bao giờ chạy Tôi cũng sẽ sử dụng các hằng số Java Integer.MAX_VALUE và Integer.MIN_VALUE thay vì các số ma thuật.
Tim the Enchanter

@TimtheEnchanter Cảm ơn bạn đã gợi ý, tôi hoàn toàn bỏ qua chúng. Trong phần chỉnh sửa của mình để kết hợp chúng, tôi đã sử dụng một biến mới trong vòng lặp for đầu tiên để tránh câu lệnh if thêm.
Wayne

1

Nếu bạn đang sử dụng API Android, bạn có thể sử dụng:

TextUtils.isDigitsOnly(str);

1

Một lựa chọn khác:

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
Điều này đang làm chính xác điều mà người đăng đang hỏi về.
Martin Carney

0

Những gì bạn đã làm, nhưng có lẽ bạn không nên luôn luôn kiểm tra theo cách đó. Ném ngoại lệ nên được dành riêng cho các tình huống "ngoại lệ" (tuy nhiên có thể phù hợp với trường hợp của bạn) và rất tốn kém về mặt hiệu suất.


Chúng chỉ tốn kém nếu chúng bị ném.
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

Điều này sẽ chỉ làm việc cho các số nguyên tích cực.

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
Chào mừng đến với stackoverflow. Trước khi hồi sinh một chủ đề cũ, hãy chắc chắn đọc các phản hồi và bình luận trước đó. Phương pháp này (và nhược điểm có thể) đã thực sự được thảo luận.
Leigh

0

Điều này làm việc cho tôi. Đơn giản chỉ cần xác định xem Chuỗi là số nguyên thủy hay số.

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

Để kiểm tra tất cả các ký tự int, bạn chỉ cần sử dụng âm kép.

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

[^ 0-9] + $ kiểm tra xem có ký tự nào không phải là số nguyên không, vì vậy kiểm tra thất bại nếu đó là sự thật. Chỉ cần KHÔNG và bạn có được thành công thực sự.


Không. Bạn rõ ràng đã không kiểm tra điều này. Điều này chỉ trả về true nếu có một chữ số ở đâu đó trong chuỗi, không phải nếu chuỗi chỉ là chữ số. Các matchesphương pháp phù hợp chống lại toàn bộ chuỗi, không chỉ là một phần của nó.
Dawood ibn Kareem

Bạn không nhận được phần tiêu cực kép.
Roger F. Gay

Chà, tôi KHÔNG nhận được tiêu cực kép. Điều này chỉ đơn giản là không hoạt động. Nếu bạn có một hỗn hợp các chữ số và chữ cái, điều này sẽ đi vào ifkhối. Nó không nên.
Dawood ibn Kareem

0

Tìm cái này có thể hữu ích:

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

0

Tôi tin rằng có không có rủi ro chạy vào một ngoại lệ, bởi vì như bạn thấy bên dưới, bạn luôn an toàn phân tích intđểString và không phải là cách khác xung quanh.

Vì thế:

  1. Bạn kiểm tra xem mọi vị trí của ký tự trong chuỗi của bạn có khớp với ít nhất một trong các ký tự {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"} .

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. Bạn tổng hợp tất cả các lần bạn gặp trong các vị trí trên các ký tự trên.

    digits++;
  3. Và cuối cùng bạn kiểm tra xem số lần bạn gặp phải số nguyên là ký tự có bằng với độ dài của chuỗi đã cho hay không.

    if(digits == aString.length())

Và trong thực tế, chúng ta có:

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

Và kết quả là:

Đó là một số nguyên !!

Nó không phải là số nguyên !!

Tương tự, bạn có thể xác nhận nếu a Stringlà a floathoặc a doublenhưng trong những trường hợp đó bạn chỉ gặp phải một. (dấu chấm) trong Chuỗi và tất nhiên kiểm tra xem digits == (aString.length()-1)

Một lần nữa, không có rủi ro khi chạy vào một ngoại lệ phân tích cú pháp ở đây, nhưng nếu bạn có kế hoạch phân tích một chuỗi mà nó được biết có chứa một số (giả sử kiểu dữ liệu int ), trước tiên bạn phải kiểm tra xem nó có phù hợp với loại dữ liệu hay không. Nếu không, bạn phải bỏ nó.

tôi mong tôi đã giúp đỡ được

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.