วิธีที่ดีที่สุดในการตรวจสอบว่าสตริงแสดงถึงจำนวนเต็มใน Java คืออะไร?


214

ปกติฉันจะใช้สำนวนต่อไปนี้เพื่อตรวจสอบว่า String สามารถแปลงเป็นจำนวนเต็มได้หรือไม่

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

มันเป็นเพียงฉันหรือว่านี้ดูเหมือนแฮ็คเล็กน้อย? เป็นวิธีที่ดีกว่าอะไร


ดูคำตอบของฉัน (พร้อมด้วยมาตรฐานอ้างอิงจากคำตอบก่อนหน้าโดยCodingWithSpike ) เพื่อดูว่าทำไมฉันถึงกลับตำแหน่งของฉันและยอมรับคำตอบของ Jonas Klemming เกี่ยวกับปัญหานี้ ฉันคิดว่าคนส่วนใหญ่จะใช้รหัสดั้งเดิมนี้ได้เนื่องจากมันใช้งานได้เร็วกว่าและบำรุงรักษาได้มากกว่า แต่คำสั่งของขนาดจะช้าลงเมื่อให้ข้อมูลที่ไม่ใช่จำนวนเต็ม


คุณมีความคิดเห็นเกี่ยวกับ RegExp สำหรับการแก้ปัญหาอย่างไร
Akshay Pethani

คำตอบ:


171

ถ้าคุณไม่ได้เกี่ยวข้องกับปัญหาที่อาจเกิดขึ้นล้นฟังก์ชั่นนี้จะดำเนินการประมาณ 20-30 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> = ':') ดูแปลกไปหน่อย ฉันจะใช้ (c <'0' || c> '9') ... ตัวดำเนินการ <= และ> = เร็วกว่าใน Java หรือไม่
ไม่เปิดเผยตัว

3
ทำไมไม่ใช้ regex ไม่ส่งคืน str.matches ("^ -? \\ d + $") เหมือนกับโค้ดด้านบน
Maglob

15
ฉันจะใช้วิธีนี้หรือวิธีเดิมจากคำถามก่อน regex นี้เพื่อประสิทธิภาพวิธีการดั้งเดิมสำหรับความเร็วของการใช้งานและการบำรุงรักษาที่แท้จริง โซลูชัน regex ไม่มีอะไรเกิดขึ้น
Bill the Lizard

4
ฉันกังวลเกี่ยวกับการล้น แต่วิธีนี้สามารถปรับให้เข้ากับ BigInts และยังเร็วกว่าวิธีอื่น ๆ ในกรณีที่มีใครสงสัยว่าทำไมฉันถึงใช้ความพยายามอย่างมากในการแก้ปัญหาอย่างง่ายฉันกำลังสร้างห้องสมุดเพื่อช่วยในการแก้ปัญหา Project Euler
Bill the Lizard

1
หากคุณกังวลว่าคุณสามารถวิเคราะห์สตริงเป็นจริงหรือไม่ก็ได้คุณจะต้องตรวจสอบว่าจำนวนเต็มที่สตริงนั้นเหมาะสมกับชนิดข้อมูลเหล่านั้นหรือไม่
Jonas K

65

คุณมี NumberFormatExceptionแต่คุณเท่านั้นที่ควรจะจับ


7
ใช่มันถือว่าเป็นรูปแบบที่ไม่ดีที่จะจับข้อยกเว้นมากกว่าที่คุณต้องการ
Chris

คุณถูก. NFE เป็นคนเดียวที่สามารถโยนได้ แต่ก็ยังเป็นนิสัยที่ไม่ดี
Bill the Lizard

ฉันคิดว่าสามารถโยน NPE ได้หากอินพุตเป็นโมฆะดังนั้นวิธีการของคุณควรจัดการกับสิ่งนั้นอย่างชัดเจนไม่ว่าคุณจะต้องการวิธีใด
Dov Wasserman

@Dov: คุณถูกต้อง NPE และ NFE ควรถูกจับได้อย่างชัดเจน
Bill the Lizard

คำตอบนี้ควรเป็นคำตอบที่แท้จริงสำหรับคำถามนี้
Breedly

40

ทำเกณฑ์มาตรฐานอย่างรวดเร็ว ข้อยกเว้นไม่ได้จริงที่ expensivve ถ้าคุณเริ่ม popping กลับหลายวิธีและ JVM ต้องทำงานมากเพื่อให้สแตกการเรียกใช้แทน เมื่ออยู่ในวิธีเดียวกันพวกเขาก็ไม่ใช่นักแสดงที่แย่

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

เอาท์พุท:

ByException: 31

ByRegex: 453 (หมายเหตุ: รวบรวมรูปแบบใหม่ทุกครั้ง)

ByJonas: 16

ฉันยอมรับว่าโซลูชันของ Jonas K นั้นแข็งแกร่งที่สุดเช่นกัน ดูเหมือนว่าเขาจะชนะ :)


13
ความคิดที่ดีในการเปรียบเทียบทั้งสาม เพื่อความเป็นธรรมกับวิธี Regex และ Jonas คุณควรทดสอบด้วยสตริงที่ไม่ใช่จำนวนเต็มเนื่องจากเป็นที่ซึ่งวิธี Integer.parseInt จะช้าลงอย่างมาก
Bill the Lizard

4
ขออภัยการทดสอบ regex นี้ไม่ดี (1) คุณไม่จำเป็นต้องทำการตรวจสอบโปรแกรม regex ^และ$ครั้งที่สองเนื่องจากในmatchesสตริงทั้งหมดจะต้องตรงกับ regex (2) str.matchesในแต่ละครั้งจะต้องสร้างตัวเองPatternซึ่งมีราคาแพง ด้วยเหตุผลด้านประสิทธิภาพเราควรสร้างรูปแบบดังกล่าวเพียงครั้งเดียวนอกวิธีการนี้และใช้ภายใน (3) เราสามารถสร้างวัตถุ Matcher ได้เพียงชิ้นเดียวและใช้reset(CharSequence)เพื่อส่งข้อมูลผู้ใช้และส่งคืนmatches()ผลลัพธ์
Pshemo

ดังนั้นสิ่งที่private final Matcher m = Pattern.compile("-?\\d+").matcher(""); private boolean byRegex(String str) { return m.reset(str).matches(); }ควรมีประสิทธิภาพดีกว่า
Pshemo

@Pshemo Integer.valueOf ("1") และ Integer.valueOf ("1") ทั้งสองข้อยกเว้นดังนั้นการตรวจสอบ ^ และ $ ดูสมเหตุสมผล
cquezel

1
@cquezel ใช่ แต่ไม่จำเป็นเนื่องจากmatchesมีการเพิ่ม^และ$โดยปริยาย ลองดูที่ผลของและ" 123".matches("\\d+") "123".matches("\\d+")คุณจะเห็นและfalse จะถูกส่งคืนเนื่องจากสตริงขึ้นต้นด้วยช่องว่างซึ่งป้องกันไม่ให้จับคู่กับ regex ทั้งหมด truefalse
Pshemo

37

เนื่องจากมีความเป็นไปได้ที่ผู้คนยังคงมาที่นี่และจะลำเอียงกับ Regex หลังจากการวัดประสิทธิภาพ ... ดังนั้นฉันจะให้การวัดประสิทธิภาพรุ่นปรับปรุงด้วย Regex รุ่นที่คอมไพล์แล้ว ซึ่งตรงข้ามกับเกณฑ์มาตรฐานก่อนหน้านี้อันนี้แสดงให้เห็นถึงวิธีการแก้ปัญหา Regex จริงมีประสิทธิภาพที่ดีอย่างต่อเนื่อง

คัดลอกมาจาก Bill the Lizard และอัปเดตด้วยรุ่นที่คอมไพล์แล้ว:

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

ผล:

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
เวลา ByCompiledRegex จำเป็นต้องรวมการรวบรวม regex ในการวัดเวลา
Martin Carney

2
@MartinCarney ฉันแก้ไขและรวบรวมรูปแบบมาตรฐาน เห็นได้ชัดว่า CPU ของฉัน / JIT จะเร็ว 336แต่ถ้าผมสอดแทรกมันกลับมาเวลารวบรวมเป็น
tedder42

2
เพื่อให้ชัดเจนว่า 336 (ms) เป็นสิ่งที่เกิดขึ้นเมื่อการรวบรวมรูปแบบเสร็จ 100k ครั้งเหมือนกับทุกบรรทัดอื่น ๆ ด้วยนัยที่ว่าจะทำเพียงครั้งเดียวเวลาของมันจึงเป็นศูนย์
tedder42

ขอบคุณสำหรับการตั้งค่าการบันทึกตรงตามเวลา regex รวบรวม
LarsH

อาจ"^[+-]?\\d+$"จะดียิ่งขึ้น
อดัม

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

แม้ว่า lib มาตรฐานของ Java จะพลาดฟังก์ชั่นยูทิลิตี้เหล่านี้จริงๆ

ฉันคิดว่า Apache Commons เป็น "ต้องมี" สำหรับโปรแกรมเมอร์ Java ทุกคน

แย่มากที่ยังไม่ได้ทำการย้ายไปยัง Java5


1
ปัญหาเดียวของเรื่องนี้ก็คือล้น: SI ยังให้ +1 สำหรับการกล่าวถึงคอมมอนส์ - lang :)
javamonkey79

2
ปัญหาอีกอย่างคือตัวเลขติดลบ แต่ฉันก็ +1 ด้วยเนื่องจากในมุมมองของฉันวิธีนี้เข้าใกล้ทางออกที่ดีที่สุด
sandris

22

ส่วนหนึ่งขึ้นอยู่กับสิ่งที่คุณหมายถึงโดย "สามารถแปลงเป็นจำนวนเต็ม"

ถ้าคุณหมายถึง "สามารถแปลงเป็น int ใน Java ได้" คำตอบจาก Jonas เป็นการเริ่มต้นที่ดี แต่ก็ยังทำงานไม่เสร็จ มันจะผ่าน 99999999999999999999999999999999 ตัวอย่างเช่น ฉันจะเพิ่มการโทรลอง / จับปกติจากคำถามของคุณเองเมื่อสิ้นสุดวิธีการ

การตรวจสอบตัวละครทีละตัวอักษรจะปฏิเสธอย่างมีประสิทธิภาพ "ไม่ใช่จำนวนเต็มเลย" โดยปล่อยให้ "มันเป็นจำนวนเต็ม แต่ Java ไม่สามารถจัดการกับ" กรณีที่จะถูกดักจับโดยเส้นทางยกเว้นที่ช้ากว่า คุณสามารถทำบิตนี้ด้วยมือเกินไป แต่มันจะเป็นจำนวนมากที่มีความซับซ้อนมากขึ้น


17

เพียงหนึ่งความคิดเห็นเกี่ยวกับ regexp ทุกตัวอย่างที่นี่ไม่ถูกต้อง! หากคุณต้องการใช้ regexp อย่าลืมว่าการรวบรวมรูปแบบต้องใช้เวลานานมาก นี้:

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

และสิ่งนี้:

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

ทำให้เกิดการรวบรวมของรูปแบบในทุกวิธีการโทร หากต้องการใช้อย่างถูกต้องให้ปฏิบัติตาม:

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
คุณสามารถบีบประสิทธิภาพเพิ่มขึ้นอีกเล็กน้อยด้วยการสร้าง Matcher ล่วงหน้าเช่นกันและใช้วิธีรีเซ็ต () เพื่อใช้กับอินพุต
อลันมัวร์

13

มีรุ่นฝรั่ง:

import com.google.common.primitives.Ints;

Integer intValue = Ints.tryParse(stringValue);

มันจะกลับมาเป็นโมฆะแทนที่จะโยนข้อยกเว้นถ้ามันไม่สามารถแยกสตริง


3
คำตอบที่ดีที่สุด IMHO ใช้ไลบรารีที่ผ่านการทดสอบอย่างดีแทนที่จะใช้วิธีแก้ปัญหาของคุณเอง (ดูการอภิปรายที่นี่ด้วย)
Olivier Cailloux

12

ฉันคัดลอกโค้ดจากคำตอบ rally25rs และเพิ่มการทดสอบบางอย่างสำหรับข้อมูลที่ไม่ใช่จำนวนเต็ม ผลลัพธ์ที่ได้ปฏิเสธไม่ได้กับวิธีการโพสต์โดย Jonas Klemming ผลลัพธ์สำหรับวิธีการยกเว้นที่ฉันโพสต์ครั้งแรกค่อนข้างดีเมื่อคุณมีข้อมูลจำนวนเต็ม แต่มันแย่ที่สุดเมื่อคุณไม่มีในขณะที่ผลลัพธ์สำหรับโซลูชัน RegEx (ซึ่งฉันจะเดิมพันผู้คนจำนวนมากใช้) ได้อย่างต่อเนื่องที่ไม่ดี ดูคำตอบของ Felipeสำหรับตัวอย่าง regex ที่รวบรวมซึ่งเร็วกว่ามาก

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

ผล:

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

สิ่งนี้สั้นกว่า แต่สั้นกว่าไม่จำเป็นต้องดีกว่า (และจะไม่จับค่าจำนวนเต็มซึ่งอยู่นอกช่วงดังที่ระบุไว้ในความคิดเห็นของ danatel ):

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

ส่วนตัวตั้งแต่การดำเนินการ squirrelled ไปในวิธีการช่วยเหลือและปั้นความถูกต้องความยาวผมก็จะไปกับสิ่งที่ชอบสิ่งที่คุณมี (ลบจับฐานExceptionระดับมากกว่าNumberFormatException)


1
และอาจ \\ d {1,10} คือถึงแม้ว่าจะไม่สมบูรณ์แบบดีกว่า \\ d + สำหรับการจับ Java Integers
Maglob

6

คุณสามารถใช้วิธีการจับคู่ของคลาสสตริง [0-9] หมายถึงค่าทั้งหมดที่สามารถเป็นได้เครื่องหมาย + หมายความว่าจะต้องมีความยาวอย่างน้อยหนึ่งตัวอักษรและ * หมายถึงมันอาจเป็นศูนย์หรือมากกว่าตัวอักษรที่มีความยาว

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 นี้ไม่ตรงกับ "+10" หรือ "-10") ซึ่งโดยปกติจะรวมอยู่ในจำนวนเต็มที่ถูกต้อง
Tim Wintle

4

เกี่ยวกับ:

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

สิ่งที่เกี่ยวกับจำนวนเต็ม 999999999999999999999999999999999999?
danatel

อย่าลืมตรวจสอบเครื่องหมายลบ
Jeremy Ruten

คุณไม่จำเป็นต้องยึดจุดเริ่มต้นและจุดสิ้นสุดของ regex ดังนั้นคุณจะไม่ผ่าน "aaa-1999zzz" ใช่ไหม
ทิมฮาวแลนด์

2
ทิมเมื่อคุณเรียกใช้หนึ่งในการแข่งขัน () วิธีการ (สตริงรูปแบบและการจับคู่แต่ละคนมีหนึ่ง) regex จะต้องตรงกับการป้อนข้อมูลทั้งหมดทำให้จุดยึดซ้ำซ้อน ในการค้นหาการจับคู่ตามที่กำหนดโดยรสชาติอื่น ๆ ของ regex ส่วนใหญ่คุณต้องใช้ Matcher # find ()
อลันมัวร์

4

นี่เป็นรูปแบบ Java 8 ของคำตอบ 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)));
}

รหัสทดสอบ:

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

ผลลัพธ์ของรหัสทดสอบ:

        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

คุณเพียงตรวจสอบ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

ถ้าอาร์เรย์สตริงของคุณมีจำนวนเต็มและสตริงแท้รหัสด้านล่างควรใช้งานได้ คุณต้องดูที่อักขระตัวแรกเท่านั้น เช่น ["4", "44", "abc", "77", "bond"]

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

3

นอกจากนี้คุณยังสามารถใช้คลาสสแกนเนอร์และใช้hasNextInt () - และสิ่งนี้ช่วยให้คุณสามารถทดสอบประเภทอื่น ๆ เช่นลอยตัวเป็นต้น


คำตอบนี้ให้คำเตือนฉันว่าฉันต้องการ ฉันลืมสแกนเนอร์โดยสิ้นเชิงมีฟังก์ชั่นดังกล่าว T-up
Hubro

2

หากคุณต้องการตรวจสอบว่าสตริงแสดงจำนวนเต็มที่เหมาะกับประเภท int หรือไม่ฉันได้ทำการดัดแปลงคำตอบของโจนัสเล็กน้อยดังนั้นสตริงที่แสดงถึงจำนวนเต็มที่มากกว่า Integer.MAX_VALUE หรือเล็กกว่า Integer.MIN_VALUE เท็จ ตัวอย่างเช่น: "3147483647" จะส่งคืนค่าเท็จเนื่องจาก 3147483647 นั้นมีขนาดใหญ่กว่า 2147483647 และเช่นเดียวกัน "-2147483649" จะส่งคืนค่าเท็จเนื่องจาก -2147483649 นั้นมีขนาดเล็กกว่า -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
คุณช่วยแก้ไขคำตอบของคุณและอธิบายว่ามันช่วยปรับปรุงคำตอบก่อนหน้านี้ที่คุณพูดถึงได้อย่างไร
Gilles Gouaillardet

ขอบคุณสำหรับคำตอบที่ดี แต่ "123" คือ 123 พร้อมกับช่องว่างถือเป็นจำนวนเต็มที่ถูกต้อง
Saikrishna Radarapu

1
@SaikrishnaRadarapu พวกเขาใช้trim()เพื่อให้เป็นตัวเลือกการออกแบบที่ชัดเจน
Guildenstern


1

คุณอาจต้องใช้กรณีการใช้งานในบัญชีด้วย:

หากส่วนใหญ่คุณคาดหวังว่าหมายเลขนั้นจะถูกต้องการจับข้อยกเว้นจะทำให้เกิดค่าใช้จ่ายด้านประสิทธิภาพเมื่อพยายามแปลงตัวเลขที่ไม่ถูกต้อง ในขณะที่เรียกร้องบางส่วนisInteger()วิธีการและแล้วแปลงใช้Integer.parseInt()จะเสมอสาเหตุที่ค่าใช้จ่ายในการปฏิบัติงานสำหรับตัวเลขที่ถูกต้อง - สตริงมีการแยกวิเคราะห์สองครั้งครั้งด้วยเช็คและครั้งเดียวโดยการแปลง


1

นี่คือการดัดแปลงของJonasรหัสที่ตรวจสอบว่าสายอักขระนั้นอยู่ในช่วงที่จะทำการแปลงเป็นจำนวนเต็มหรือไม่

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
ดูดี แต่สำหรับ for-loop สุดท้ายจำเป็นต้องให้ฉันรีเซ็ตเป็นศูนย์ (หรือ 1 ถ้าจำนวนลบ) เนื่องจากการวนซ้ำที่ตรวจสอบว่าแต่ละหลักเป็นตัวเลขจะส่งผลให้ฉันเป็นความยาวสตริงดังนั้นสุดท้ายสำหรับวง จะไม่วิ่ง ฉันจะใช้ค่าคงที่ของ Java Integer.MAX_VALUE และ Integer.MIN_VALUE แทนหมายเลขเวทย์มนตร์
Tim the Enchanter

@ TimtheEnchanter ขอบคุณสำหรับคำแนะนำฉันมองข้ามพวกเขาไปโดยสิ้นเชิง ในการแก้ไขของฉันเพื่อรวมพวกเขาฉันใช้ตัวแปรใหม่ในครั้งแรกสำหรับวงเพื่อหลีกเลี่ยงการเสริมถ้าคำสั่ง
เวย์น


1

ตัวเลือกอื่น:

private boolean isNumber(String s) {
    boolean isNumber = true;
    for (char c : s.toCharArray()) {
        isNumber = isNumber && Character.isDigit(c);
    }
    return isNumber;
}


0

สิ่งที่คุณใช้งานได้ แต่คุณไม่ควรตรวจสอบวิธีนี้เสมอ การโยนข้อยกเว้นควรถูกสงวนไว้สำหรับสถานการณ์ "พิเศษ" (อาจเหมาะกับกรณีของคุณ) และมีค่าใช้จ่ายสูงมากในแง่ของประสิทธิภาพ


พวกเขาจะมีราคาแพงถ้าพวกเขาถูกโยน
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

สิ่งนี้จะทำงานเฉพาะกับจำนวนเต็มบวก

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
ยินดีต้อนรับสู่ stackoverflow ก่อนที่จะคืนชีพเธรดเก่าให้แน่ใจว่าได้อ่านคำตอบและความคิดเห็นก่อนหน้านี้ วิธีการนี้ (และข้อเสียที่เป็นไปได้) ได้มีการหารือกันจริง ๆ แล้ว
Leigh

0

มันใช้งานได้สำหรับฉัน เพียงเพื่อระบุว่า String เป็นแบบดั้งเดิมหรือตัวเลข

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

ในการตรวจสอบตัวอักษรทั้งหมดคุณสามารถใช้ค่าลบสองครั้งได้

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

[^ 0-9] + $ จะตรวจสอบว่ามีอักขระใด ๆ ที่ไม่ใช่จำนวนเต็มหรือไม่ดังนั้นการทดสอบจะล้มเหลวหากเป็นจริง ไม่ใช่แค่นั้นและคุณจะได้รับความสำเร็จ


ไม่คุณยังไม่ได้ทดสอบสิ่งนี้อย่างชัดเจน สิ่งนี้จะส่งกลับค่าจริงถ้ามีตัวเลขหนึ่งในสตริงไม่ใช่ถ้าสตริงเป็นตัวเลข matchesวิธีการตรงกับสตริงทั้งหมดไม่ได้เป็นเพียงส่วนหนึ่งของมัน
Dawood ibn Kareem

คุณไม่ได้ส่วนที่เป็นลบสองเท่า
Roger F. Gay

ฉันไม่ได้รับค่าลบสองเท่า สิ่งนี้ใช้ไม่ได้ผล หากคุณมีตัวเลขและตัวอักษรผสมกันสิ่งนี้จะเข้าสู่ifบล็อก มันไม่ควร
Dawood ibn Kareem

0

ค้นหาสิ่งนี้อาจเป็นประโยชน์:

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

0

ผมเชื่อว่ามีความเสี่ยงการทำงานเป็นข้อยกเว้นศูนย์เพราะเท่าที่คุณสามารถดูด้านล่างคุณได้อย่างปลอดภัยแยกintไปStringและไม่วิธีอื่น ๆ

ดังนั้น:

  1. คุณตรวจสอบว่าทุกช่องของตัวละครในสตริงของคุณตรงกับอักขระอย่างน้อยหนึ่งตัว{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}

    if(aString.substring(j, j+1).equals(String.valueOf(i)))
  2. คุณรวมทุกครั้งที่คุณพบในช่องอักขระข้างต้น

    digits++;
  3. และสุดท้ายคุณตรวจสอบว่าเวลาที่คุณพบจำนวนเต็มเป็นตัวละครเท่ากับความยาวของสตริงที่กำหนด

    if(digits == aString.length())

และในทางปฏิบัติเรามี:

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

และผลลัพธ์คือ:

มันเป็นจำนวนเต็ม !!

ไม่ใช่จำนวนเต็ม !!

ในทำนองเดียวกันคุณสามารถตรวจสอบหากStringเป็นfloatหรือdoubleแต่ในกรณีที่คุณต้องพบเพียงหนึ่ง (dot) ใน String และแน่นอนตรวจสอบว่า digits == (aString.length()-1)

อีกครั้งมีความเสี่ยงเป็นศูนย์ที่ทำงานเป็นข้อยกเว้นการแยกวิเคราะห์ที่นี่ แต่ถ้าคุณวางแผนในการแยกสตริงที่เป็นที่รู้จักกันว่ามีจำนวน (สมมติว่าชนิดข้อมูลint ) คุณต้องตรวจสอบก่อนว่ามันเหมาะกับประเภทข้อมูล มิฉะนั้นคุณจะต้องโยนมัน

ฉันหวังว่าฉันช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.