Java String - Lihat apakah string hanya berisi angka dan bukan huruf

195

Saya memiliki string yang saya muat di seluruh aplikasi saya, dan itu berubah dari angka menjadi huruf dan semacamnya. Saya memiliki ifpernyataan sederhana untuk melihat apakah itu mengandung huruf atau angka tetapi, ada sesuatu yang tidak berfungsi dengan benar. Ini potongannya.

String text = "abc"; 
String number; 

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

Meskipun textvariabel tidak mengandung huruf, kondisinya kembali sebagai true. Dan &&harus mengevaluasi karena kedua kondisi harus trueuntuk memprosesnumber = text;

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

Larutan:

Saya dapat menyelesaikan ini dengan menggunakan kode berikut yang disediakan oleh komentar pada pertanyaan ini. Semua posting lain juga valid!

Apa yang saya gunakan yang berfungsi berasal dari komentar pertama. Meskipun semua kode contoh yang diberikan tampaknya juga valid!

String text = "abc"; 
String number; 

if (Pattern.matches("[a-zA-Z]+", text) == false && text.length() > 2) {
    number = text; 
}
RedHatcc
sumber
5
mengandung tidak mengambil regexp sebagai input. Gunakan salah satu matches("\\d{2,}")atau coba dengan PatterndanMatcher
Guillaume Polet
Bisakah string memiliki nilai desimal atau hanya nilai integer?
pseudoramble
3
Mengapa Anda memeriksa text.length ()> 2? Apa alasannya?
Code Enthusiastic
1
@RedHatcc Pattern.matches("[a-zA-Z]+", text) == falsedapat disederhanakan menjadi!Pattern.matches("[a-zA-Z]+", text)
SARose
2
Menggunakan java streaming, boolean isNumeric = someString.chars().allMatch(x -> Character.isDigit(x));bentuk Max Malyshposting.
Yash

Jawaban:

354

Jika Anda akan memproses angka sebagai teks, maka ubah:

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

untuk:

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

Alih-alih memeriksa bahwa string tidak mengandung karakter alfabet, periksa untuk memastikan string hanya berisi angka.

Jika Anda benar-benar ingin menggunakan nilai numerik, gunakan Integer.parseInt()atau Double.parseDouble()seperti yang dijelaskan orang lain di bawah ini.


Sebagai catatan, umumnya dianggap praktik buruk untuk membandingkan nilai boolean trueatau false. Cukup gunakan if (condition)atau if (!condition).

Adam Liss
sumber
25
Anda mungkin ingin menambahkan jangkar (mis. ^[0-9]+$) Jika tidak abc123defakan dianggap angka.
ICR
10
Saya pikir itu tidak perlu. matches()mengembalikan true jika dan hanya jika itu benar-benar cocok dari awal hingga akhir.
Proyek Chthonic
4
"^ -? \ d + \.? \ d * $" akan membandingkan seluruh string dan hanya cocok jika itu adalah angka yang valid (termasuk negatif dan desimal). Misalnya, itu akan cocok dengan 1, 10, 1.0, -1, -1.0, dll. Ini juga akan cocok dengan "1." tapi itu sering bisa diuraikan.
16
Tidak perlu menelepon && (text.length() > 2). Semuanya dapat diperiksa dalam pola regex:if (text.matches("[0-9]{3,}")
ctomek
Bagaimana dengan koma atau titik untuk angka yang bukan bilangan bulat?
nibbana
20

Anda juga dapat menggunakan NumberUtil.isCreatable (String str) dari Apache Commons

Dhrumil Shah
sumber
4
Saya pikir NumberUtil.isCreatable(String str)itu tidak benar untuk digunakan untuk apa yang ditanyakan oleh pertanyaan awal. Misalnya, NumberUtil.isCreatable( "09" )pengembalian false, meskipun "09" hanya berisi angka .
Abdull
14

Inilah yang akan saya lakukan:

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

The $akan menghindari parsial pertandingan misalnya; 1B.

tokhi
sumber
1
Saya tidak membutuhkan text.length() > 2bagian, jadi saya hanya mengganti ^[0-9]*$dengan ^[0-9]+$untuk memastikan saya memiliki setidaknya satu nomor.
YB Menyebabkan
8

Kinerja-bijaksana parseIntdan semacamnya jauh lebih buruk daripada solusi lain, karena setidaknya memerlukan penanganan pengecualian.

Saya telah menjalankan tes jmh dan telah menemukan bahwa iterasi dari String menggunakan charAtdan membandingkan karakter dengan karakter batas adalah cara tercepat untuk menguji apakah string hanya berisi angka.

Pengujian JMH

Tes membandingkan kinerja nilai char Character.isDigitvs Pattern.matcher().matchesvs Long.parseLongvs.

Cara-cara ini dapat menghasilkan hasil yang berbeda untuk string non-ascii dan string yang mengandung tanda +/-.

Tes dijalankan dalam mode Throughput ( lebih besar lebih baik ) dengan 5 iterasi pemanasan dan 5 iterasi tes.

Hasil

Perhatikan bahwa parseLonghampir 100 kali lebih lambat daripada isDigituntuk beban uji pertama.

## 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

Suite uji

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

Diperbarui pada 23 Feb 2018

  • Tambahkan dua case lagi - satu menggunakan charAtalih-alih membuat array tambahan dan menggunakan IntStreamkode char lainnya
  • Tambahkan istirahat segera jika non-digit ditemukan untuk kasus uji berulang
  • Mengembalikan false untuk string kosong untuk kasus uji berulang

Diperbarui pada 23 Feb 2018

  • Tambahkan satu lagi test case (tercepat!) Yang membandingkan nilai char tanpa menggunakan stream
Anton R
sumber
1
Jika Anda melihat kode toCharArray, itu mengalokasikan array char dan menyalin chars (saya pikir itu bisa mahal). Bagaimana jika Anda hanya mengulangi string menggunakan indeks dan karakter, apakah itu akan lebih cepat? Akan menarik juga jika Anda dapat menambahkan solusi dari Andy ke tes Anda: boolean isNum = text.chars (). AllMatch (c -> c> = 48 && c <= 57)
Aldo Canepa
8

Untuk cukup memeriksa string yang hanya berisi ALPHABETS, gunakan kode berikut:

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

Untuk memeriksa string yang berisi NUMBER hanya gunakan kode berikut:

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

Semoga ini bisa membantu seseorang!

Aman Kumar Gupta
sumber
3

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

Andy
sumber
1
untuk mengurangi angka ajaib, Anda dapat membandingkan sebagai berikut:boolean isNum = text.chars().allMatch(c -> c >= '0' && c <= '9')
Phe0nix
2

Anda dapat menggunakan Regex.Match

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

Atau Anda dapat menggunakan konversi suka Integer.parseInt(String)atau lebih baik Long.parseLong(String)untuk angka yang lebih besar seperti misalnya:

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

Dan kemudian uji dengan:

if (onlyContainsNumbers(text) && text.length() > 2) {
    // do Stuff
}
Yannjoel
sumber
.matches ("^ \\ d + $")
CrandellWS
2

Regex di bawah ini dapat digunakan untuk memeriksa apakah string hanya memiliki nomor atau tidak:

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

Kedua kondisi di atas akan kembali truejika String berisi non-angka. Nyala false, string hanya memiliki angka.

Nitesh Shrivastava
sumber
2

Apache Commons Lang menyediakan org.apache.commons.lang.StringUtils.isNumeric(CharSequence cs), yang mengambil sebagai argumen a Stringdan memeriksa apakah itu terdiri dari karakter numerik murni (termasuk angka dari skrip non-Latin). Metode itu kembali falsejika ada karakter seperti pemisah spasi, minus, plus, dan desimal seperti koma dan titik.

Metode lain dari kelas itu memungkinkan untuk pemeriksaan numerik lebih lanjut.

Abdull
sumber
1
Ini harusnya jauh lebih cepat daripada regex; inilah implementasinya: 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

Ada banyak fasilitas untuk mendapatkan nomor dari Stringdi Jawa (dan sebaliknya). Anda mungkin ingin melewati bagian regex untuk menghindari kerumitan itu sendiri.

Misalnya, Anda dapat mencoba dan melihat apa yang Double.parseDouble(String s)kembali untuk Anda. Ini harus melempar NumberFormatExceptionjika tidak menemukan nilai yang sesuai dalam string. Saya akan menyarankan teknik ini karena Anda benar-benar dapat menggunakan nilai yang diwakili oleh Stringsebagai tipe numerik.

pseudoramble
sumber
5
Menggunakan pengecualian sebagai alasan untuk menguji input Anda mungkin merupakan ide yang buruk, pengecualian membuat overhead yang besar.
Ofir Luzon
1
@OfirLuzon Saya setuju bahwa pengecualian bukan cara yang bagus untuk menangani kasus yang diharapkan yang akan muncul. Namun saya pikir sulit untuk mengatakan apakah akan ada kinerja yang berhasil tanpa lebih banyak konteks.
pseudoramble
1

Ini kode saya, semoga ini membantu Anda!

 public boolean isDigitOnly(String text){

    boolean isDigit = false;

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

    return isDigit;
}
Saurabh Gaddelpalliwar
sumber
0

Kode ini sudah ditulis. Jika Anda tidak keberatan dengan hit kinerja sangat kecil - yang mungkin tidak lebih buruk daripada melakukan pertandingan regex - gunakan Integer.parseInt () atau Double.parseDouble () . Itu akan memberitahu Anda segera jika String hanya nomor (atau adalah nomor, yang sesuai). Jika Anda perlu menangani string angka yang lebih lama, konstruktor olahraga BigInteger dan BigDecimal yang menerima string. Semua ini akan melempar NumberFormatException jika Anda mencoba memberikannya non-angka (integral atau desimal, berdasarkan yang Anda pilih, tentu saja). Bergantian, tergantung pada kebutuhan Anda, hanya iterate karakter dalam String dan periksa Character.isDigit ()dan / atau Character.isLetter () .

Ryan Stewart
sumber
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;
    }
}
Usman Javaid
sumber
0
Character first_letter_or_number = query.charAt(0);
                //------------------------------------------------------------------------------
                if (Character.isDigit())
                {

                }
                else if (Character.isLetter())
                {

                }
JamisonMan111
sumber
0

Contoh tes kerja

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

Masih kode Anda dapat dipecah oleh "1a" dll sehingga Anda perlu memeriksa pengecualian

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

Metode untuk memeriksa tidak adalah string atau tidak

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

Merupakan praktik yang buruk untuk melibatkan pengecualian melempar / menangani skenario seperti itu.

Oleh karena itu parseInt () tidak bagus, tetapi regex adalah solusi yang elegan untuk ini, tetapi perhatikan hal berikut:
-fraksi
-negatif angka
-Pemisah spesifik mungkin berbeda dalam contries (misalnya ',' atau '.')
-Sometimes itu diizinkan untuk memiliki apa yang disebut pemisah ribuan, seperti spasi atau koma misalnya 12.324.1000.355

Untuk menangani semua kasus yang diperlukan dalam aplikasi Anda, Anda harus berhati-hati, tetapi regex ini mencakup skenario tipikal (positif / negatif dan fraksional, dipisahkan oleh titik): ^ [- +]? \ D *.? \ D + $
Untuk pengujian, saya sarankan regexr.com .

Adam Bodrogi
sumber
0

Versi Adam Bodrogi yang sedikit dimodifikasi:

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

Harus menggunakan ini hari ini jadi pasang saja modifikasi saya. Termasuk mata uang, ribuan koma atau notasi periode, dan beberapa validasi. Tidak termasuk notasi mata uang lainnya (euro, sen), koma verifikasi adalah setiap digit ketiga.

pengguna176692
sumber