Chuỗi Java - Xem nếu một chuỗi chỉ chứa số và không phải chữ cái


195

Tôi có một chuỗi mà tôi tải trong suốt ứng dụng của mình và nó thay đổi từ số sang chữ và như vậy. Tôi có một iftuyên bố đơn giản để xem nó có chứa các chữ cái hoặc số hay không, nhưng một cái gì đó không hoạt động chính xác. Đây là một đoạn.

String text = "abc"; 
String number; 

if (text.contains("[a-zA-Z]+") == false && text.length() > 2) {
    number = text; 
}

Mặc dù textbiến không chứa các chữ cái, điều kiện trả về là true. Cả và &&nên đánh giá cả hai điều kiện phải có trueđể xử lýnumber = text;

==============================

Giải pháp:

Tôi đã có thể giải quyết điều này bằng cách sử dụng mã sau đây được cung cấp bởi một nhận xét về câu hỏi này. Tất cả các bài viết khác là hợp lệ là tốt!

Những gì tôi sử dụng mà làm việc đến từ bình luận đầu tiên. Mặc dù tất cả các mã ví dụ được cung cấp dường như cũng hợp lệ!

String text = "abc"; 
String number; 

if (Pattern.matches("[a-zA-Z]+", text) == false && text.length() > 2) {
    number = text; 
}

5
chứa không lấy một biểu thức chính quy làm đầu vào. Sử dụng matches("\\d{2,}")hoặc thử với một PatternMatcher
Guillaume Polet

Chuỗi có thể có một giá trị thập phân hoặc chỉ các giá trị số nguyên?
bút danh

3
Tại sao bạn kiểm tra text.length ()> 2? Lý do là gì?
Mã nhiệt tình

1
@RedHatcc Pattern.matches("[a-zA-Z]+", text) == falsecó thể được đơn giản hóa thành!Pattern.matches("[a-zA-Z]+", text)
SARose

2
Sử dụng java boolean isNumeric = someString.chars().allMatch(x -> Character.isDigit(x));biểu mẫu API trực tuyến Max Malysh.
Yash

Câu trả lời:


354

Nếu bạn sẽ xử lý số dưới dạng văn bản, thì hãy thay đổi:

if (text.contains("[a-zA-Z]+") == false && text.length() > 2){

đến:

if (text.matches("[0-9]+") && text.length() > 2) {

Thay vì kiểm tra xem chuỗi không chứa các ký tự chữ cái, hãy kiểm tra để chắc chắn rằng chuỗi đó chỉ chứa các số.

Nếu bạn thực sự muốn sử dụng giá trị số, hãy sử dụng Integer.parseInt()hoặc Double.parseDouble()như những người khác đã giải thích bên dưới.


Là một lưu ý phụ, nó thường được coi là thực hành xấu để so sánh các giá trị boolean với truehoặc false. Chỉ cần sử dụng if (condition)hoặc if (!condition).


25
Bạn có thể muốn thêm các neo (ví dụ ^[0-9]+$) nếu không abc123defsẽ được coi là một số.
ICR

10
Tôi không nghĩ đó là bắt buộc. matches()trả về true nếu và chỉ khi đó là một kết hợp hoàn chỉnh từ đầu đến cuối.
Dự án Chthonic

4
"^ -? \ d + \.? \ D * $" sẽ so sánh toàn bộ chuỗi và chỉ khớp nếu đó là một số hợp lệ (bao gồm cả số âm và số thập phân). Ví dụ: nó sẽ khớp với 1, 10, 1.0, -1, -1.0, v.v. Nó cũng sẽ khớp với "1." nhưng điều đó thường có thể được phân tích cú pháp

16
Không cần phải gọi && (text.length() > 2). Mọi thứ đều có thể được kiểm tra theo mẫu regex:if (text.matches("[0-9]{3,}")
ctomek

Còn dấu phẩy hoặc dấu chấm cho các số không phải là số nguyên thì sao?
niết bàn

20

Bạn cũng có thể sử dụng NumberUtil.isCreatable (Chuỗi str) từ Apache Commons


4
Tôi không nghĩ NumberUtil.isCreatable(String str)là chính xác để sử dụng cho những gì câu hỏi ban đầu yêu cầu. Ví dụ, NumberUtil.isCreatable( "09" )trả về false, mặc dù "09" chỉ chứa số .
Abdull

14

Đây là cách tôi sẽ làm điều đó:

if(text.matches("^[0-9]*$") && text.length() > 2){
    //...
}

Các $sẽ tránh được một trận đấu như một phần; 1B.


1
Tôi không cần text.length() > 2một phần, vì vậy tôi chỉ thay thế ^[0-9]*$bởi ^[0-9]+$để chắc chắn tôi có ít nhất một số.
YB Nguyên nhân

8

Hiệu suất khôn ngoan parseIntvà như vậy là tồi tệ hơn nhiều so với các giải pháp khác, bởi vì ít nhất yêu cầu xử lý ngoại lệ.

Tôi đã chạy thử nghiệm jmh và nhận thấy rằng việc lặp qua Chuỗi bằng cách sử dụng charAtvà so sánh ký tự với ký tự biên là cách nhanh nhất để kiểm tra nếu chuỗi chỉ chứa các chữ số.

Thử nghiệm JMH

Các thử nghiệm so sánh hiệu suất của Character.isDigitvs Pattern.matcher().matchesvs Long.parseLongvs kiểm tra giá trị char.

Những cách này có thể tạo ra kết quả khác nhau cho các chuỗi không phải chuỗi ascii và chuỗi chứa dấu +/-.

Các thử nghiệm chạy ở chế độ Thông lượng ( lớn hơn là tốt hơn ) với 5 lần lặp khởi động và 5 lần lặp thử nghiệm.

Các kết quả

Lưu ý rằng parseLongchậm hơn gần 100 lần so isDigitvới tải thử nghiệm đầu tiên.

## Test load with 25% valid strings (75% strings contain non-digit symbols)

Benchmark       Mode  Cnt  Score   Error  Units
testIsDigit    thrpt    5  9.275 ± 2.348  ops/s
testPattern    thrpt    5  2.135 ± 0.697  ops/s
testParseLong  thrpt    5  0.166 ± 0.021  ops/s

## Test load with 50% valid strings (50% strings contain non-digit symbols)

Benchmark              Mode  Cnt  Score   Error  Units
testCharBetween       thrpt    5  16.773 ± 0.401  ops/s
testCharAtIsDigit     thrpt    5  8.917 ± 0.767  ops/s
testCharArrayIsDigit  thrpt    5  6.553 ± 0.425  ops/s
testPattern           thrpt    5  1.287 ± 0.057  ops/s
testIntStreamCodes    thrpt    5  0.966 ± 0.051  ops/s
testParseLong         thrpt    5  0.174 ± 0.013  ops/s
testParseInt          thrpt    5  0.078 ± 0.001  ops/s

Bộ kiểm tra

@State(Scope.Benchmark)
public class StringIsNumberBenchmark {
    private static final long CYCLES = 1_000_000L;
    private static final String[] STRINGS = {"12345678901","98765432177","58745896328","35741596328", "123456789a1", "1a345678901", "1234567890 "};
    private static final Pattern PATTERN = Pattern.compile("\\d+");

    @Benchmark
    public void testPattern() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                b = PATTERN.matcher(s).matches();
            }
        }
    }

    @Benchmark
    public void testParseLong() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                try {
                    Long.parseLong(s);
                    b = true;
                } catch (NumberFormatException e) {
                    // no-op
                }
            }
        }
    }

    @Benchmark
    public void testCharArrayIsDigit() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (char c : s.toCharArray()) {
                    b = Character.isDigit(c);
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }

    @Benchmark
    public void testCharAtIsDigit() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (int j = 0; j < s.length(); j++) {
                    b = Character.isDigit(s.charAt(j));
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }

    @Benchmark
    public void testIntStreamCodes() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                b = s.chars().allMatch(c -> c > 47 && c < 58);
            }
        }
    }

    @Benchmark
    public void testCharBetween() {
        for (int i = 0; i < CYCLES; i++) {
            for (String s : STRINGS) {
                boolean b = false;
                for (int j = 0; j < s.length(); j++) {
                    char charr = s.charAt(j);
                    b = '0' <= charr && charr <= '9';
                    if (!b) {
                        break;
                    }
                }
            }
        }
    }
}

Cập nhật vào ngày 23 tháng 2 năm 2018

  • Thêm hai trường hợp nữa - một trường hợp sử dụng charAtthay vì tạo mảng bổ sung và trường hợp khác sử dụng IntStreammã char
  • Thêm ngắt ngay lập tức nếu không tìm thấy chữ số cho các trường hợp kiểm tra lặp
  • Trả về false cho chuỗi rỗng cho các trường hợp kiểm tra lặp

Cập nhật vào ngày 23 tháng 2 năm 2018

  • Thêm một trường hợp thử nghiệm (nhanh nhất!) So sánh giá trị char mà không cần sử dụng luồng

1
Nếu bạn nhìn vào mã của toCharArray, nó đang phân bổ một mảng char và sao chép các ký tự (tôi nghĩ rằng nó có thể tốn kém). Thế còn nếu bạn chỉ lặp lại chuỗi bằng chỉ mục và charAt, nó có nhanh hơn không? Sẽ rất thú vị nếu bạn có thể thêm giải pháp từ Andy vào các bài kiểm tra của mình: boolean isNum = text.chars (). AllMatch (c -> c> = 48 && c <= 57)
Aldo Canepa

8

Để chỉ cần kiểm tra chuỗi có chứa ALPHABETS, hãy sử dụng mã sau:

if (text.matches("[a-zA-Z]+"){
   // your operations
}

Để chỉ cần kiểm tra chuỗi có chứa SỐ, hãy sử dụng đoạn mã sau:

if (text.matches("[0-9]+"){
   // your operations
}

Hy vọng điều này sẽ giúp cho một ai đó!


3

boolean isNum = text.chars (). allMatch (c -> c> = 48 && c <= 57)


1
để giảm số lượng ma thuật, bạn có thể so sánh như sau:boolean isNum = text.chars().allMatch(c -> c >= '0' && c <= '9')
Phe0nix

2

Bạn có thể sử dụng Regex.Match

if(text.matches("\\d*")&& text.length() > 2){
    System.out.println("number");
}

Hoặc bạn có thể sử dụng các thay đổi thích Integer.parseInt(String)hoặc tốt hơn Long.parseLong(String)cho các số lớn hơn như ví dụ:

private boolean onlyContainsNumbers(String text) {
    try {
        Long.parseLong(text);
        return true;
    } catch (NumberFormatException ex) {
        return false;
    }
} 

Và sau đó thử nghiệm với:

if (onlyContainsNumbers(text) && text.length() > 2) {
    // do Stuff
}

.matches ("^ \\ d + $")
CrandellWS

2

Dưới đây regex có thể được sử dụng để kiểm tra xem một chuỗi chỉ có số hay không:

if (str.matches(".*[^0-9].*")) or if (str.matches(".*\\D.*"))

Cả hai điều kiện trên sẽ trả về truenếu String tạo ra các số không. Trên false, chuỗi chỉ có số.


2

Apache Commons Lang cung cấp org.apache.commons.lang.StringUtils.isNumeric(CharSequence cs), lấy tham số a Stringvà kiểm tra xem nó có bao gồm các ký tự số thuần túy hay không (bao gồm các số từ các tập lệnh phi Latinh). Phương thức đó trả về falsenếu có các ký tự như dấu cách, dấu trừ, dấu cộng và dấu phân cách thập phân như dấu phẩy và dấu chấm.

Các phương thức khác của lớp đó cho phép kiểm tra số tiếp theo.


1
Điều này sẽ nhanh hơn rất nhiều so với regex; Đây là cách thực hiện: public static boolean isNumeric(String str) { if (str == null) { return false; } else { int sz = str.length(); for(int i = 0; i < sz; ++i) { if (!Character.isDigit(str.charAt(i))) { return false; } } return true; } }
Leo

1

Có rất nhiều phương tiện để lấy số từ Strings trong Java (và ngược lại). Bạn có thể muốn bỏ qua phần regex để dành cho mình sự phức tạp của điều đó.

Ví dụ, bạn có thể thử và xem những gì Double.parseDouble(String s)trả lại cho bạn. Nó sẽ ném một NumberFormatExceptionnếu nó không tìm thấy một giá trị thích hợp trong chuỗi. Tôi muốn đề xuất kỹ thuật này bởi vì bạn thực sự có thể sử dụng giá trị được biểu thị bằng Stringkiểu số.


5
Sử dụng một ngoại lệ như một lý do để kiểm tra đầu vào của bạn có thể là một ý tưởng tồi, các ngoại lệ tạo ra một chi phí lớn.
Ofir Luzon

1
@OfirLuzon Tôi đồng ý rằng các trường hợp ngoại lệ không phải là một cách tuyệt vời để xử lý các trường hợp dự kiến ​​sẽ phát sinh. Tuy nhiên tôi nghĩ thật khó để biết liệu sẽ có một màn trình diễn thành công mà không có nhiều bối cảnh hay không.
giả hành

1

Đây là mã của tôi, hy vọng điều này sẽ giúp bạn!

 public boolean isDigitOnly(String text){

    boolean isDigit = false;

    if (text.matches("[0-9]+") && text.length() > 2) {
        isDigit = true;
    }else {
        isDigit = false;
    }

    return isDigit;
}

0

Mã này đã được viết. Nếu bạn không quan tâm đến hiệu suất nhỏ (cực kỳ) - có lẽ không tệ hơn so với thực hiện một trận đấu regex - hãy sử dụng Integer.parseInt () hoặc Double.parseDouble () . Điều đó sẽ cho bạn biết ngay nếu Chuỗi chỉ là số (hoặc số, nếu phù hợp). Nếu bạn cần xử lý các chuỗi số dài hơn, cả hai nhà xây dựng thể thao BigIntegerBigDecimal đều chấp nhận Chuỗi. Bất kỳ thứ nào trong số này sẽ ném NumberFormatException nếu bạn cố gắng chuyển cho nó một số không (số nguyên hoặc số thập phân, dựa trên số bạn chọn, tất nhiên). Cách khác, tùy thuộc vào yêu cầu của bạn, chỉ cần lặp lại các ký tự trong Chuỗi và kiểm tra Character.isDigit ()và / hoặc Nhân vật.isLetter () .


0
import java.util.*;

class Class1 {
    public static void main(String[] argh) {
        boolean ans = CheckNumbers("123");
        if (ans == true) {
            System.out.println("String contains numbers only");
        } else {
            System.out.println("String contains other values as well");

        }
    }


    public static boolean CheckNumbers(String input) {
        for (int ctr = 0; ctr < input.length(); ctr++) {
            if ("1234567890".contains(Character.valueOf(input.charAt(ctr)).toString())) {
                continue;
            } else {
                return false;
            }
        }
        return true;
    }
}

0
Character first_letter_or_number = query.charAt(0);
                //------------------------------------------------------------------------------
                if (Character.isDigit())
                {

                }
                else if (Character.isLetter())
                {

                }

0

Ví dụ kiểm tra làm việc

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang3.StringUtils;

public class PaserNo {

    public static void main(String args[]) {

        String text = "gg";

        if (!StringUtils.isBlank(text)) {
            if (stringContainsNumber(text)) {
                int no=Integer.parseInt(text.trim());
                System.out.println("inside"+no);

            } else {
                System.out.println("Outside");
            }
        }
        System.out.println("Done");
    }

    public static boolean stringContainsNumber(String s) {
        Pattern p = Pattern.compile("[0-9]");
        Matcher m = p.matcher(s);
        return m.find();
    }
}

Tuy nhiên, mã của bạn có thể bị phá vỡ bởi "1a", v.v. vì vậy bạn cần kiểm tra ngoại lệ

if (!StringUtils.isBlank(studentNbr)) {
                try{
                    if (isStringContainsNumber(studentNbr)){
                    _account.setStudentNbr(Integer.parseInt(studentNbr.trim()));
                }
                }catch(Exception e){
                    e.printStackTrace();
                    logger.info("Exception during parse studentNbr"+e.getMessage());
                }
            }

Phương pháp kiểm tra không có chuỗi hay không

private boolean isStringContainsNumber(String s) {
        Pattern p = Pattern.compile("[0-9]");
        Matcher m = p.matcher(s);
        return m.find();
    }

0

Đó là một thực tế xấu khi liên quan đến bất kỳ ngoại lệ ném / xử lý vào một kịch bản điển hình như vậy.

Vì vậy một parseInt () không phải là tốt đẹp, nhưng một regex là một giải pháp thanh lịch cho điều này, nhưng chăm sóc những điều sau đây:
-fractions
số -phủ định
-decimal tách có thể khác nhau trong contries ( '' ví dụ '' hoặc)
-Đôi khi nó được phép có cái gọi là dấu phân cách nghìn, như dấu cách hoặc dấu phẩy, ví dụ: 12.324.1000.355

Để xử lý tất cả các trường hợp cần thiết trong ứng dụng của bạn, bạn phải cẩn thận, nhưng regex này bao gồm các kịch bản điển hình (dương / âm và phân số, cách nhau bằng dấu chấm): ^ [- +]? \ D *.? \ D + $
For thử nghiệm, tôi khuyên bạn nên regexr.com .


0

Phiên bản sửa đổi một chút của Adam Bodrogi's:

public class NumericStr {


public static void main(String[] args) {
    System.out.println("Matches: "+NumericStr.isNumeric("20"));         // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("20,00"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("30.01"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("30,000.01"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("-2980"));          // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("$20"));            // Should be true
    System.out.println("Matches: "+NumericStr.isNumeric("jdl"));            // Should be false
    System.out.println("Matches: "+NumericStr.isNumeric("2lk0"));           // Should be false
}

public static boolean isNumeric(String stringVal) {
    if (stringVal.matches("^[\\$]?[-+]?[\\d\\.,]*[\\.,]?\\d+$")) {
        return true;
    }

    return false;
}
}

Phải sử dụng cái này hôm nay nên mới đăng bài sửa đổi của tôi. Bao gồm tiền tệ, hàng ngàn dấu phẩy hoặc ký hiệu thời gian và một số xác nhận. Không bao gồm các ký hiệu tiền tệ khác (euro, cent), dấu phẩy xác minh là mỗi chữ số thứ ba.

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.