Java字符串 - 查看字符串是否仅包含数字而不是字母

255

我有一个字符串在我的应用程序中加载,它会从数字变成字母等等。我有一个简单的if语句来判断它是否包含字母或数字,但是似乎有些东西不正确。这里是一小段代码。

String text = "abc"; 
String number; 

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

虽然 text 变量包含字母,但条件返回 true。使用 && 运算符时,两个条件都必须为 true 才能处理 number = text;

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

解决方案:

我通过使用在此问题的评论中提供的以下代码解决了这个问题。所有其他帖子也是有效的!

我使用的代码来自第一条评论。虽然所有提供的示例代码似乎也是有效的!

String text = "abc"; 
String number; 

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

5
contains 不接受正则表达式作为输入。请使用 matches("\\d{2,}"),或尝试使用 PatternMatcher - Guillaume Polet
字符串可以有小数值吗,还是只能是整数值? - pseudoramble
5
你为什么要检查text.length() > 2?有什么原因? - Code Enthusiastic
1
@RedHatcc Pattern.matches("[a-zA-Z]+", text) == false 可以简化为 !Pattern.matches("[a-zA-Z]+", text) - SARose
7
使用Java流API的代码片段:boolean isNumeric = someString.chars().allMatch(x -> Character.isDigit(x));,来源于Max Malysh 的帖子。该代码可用于判断一个字符串是否为数字。 - Yash
这个负正则表达式对我来说似乎最简单:! oddStr.matches("\\D+") - MarkHu
25个回答

428

如果你将以文本形式处理该数字,则更改:

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

发送至:

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

不要检查字符串中是否不包含字母,而是要确保它只包含数字。

如果您真的想使用数值,请像其他人已经解释的那样使用Integer.parseInt()Double.parseDouble()


顺便说一下,在比较布尔值与truefalse时,通常被认为是不好的做法。只需使用if(条件)if(!条件)即可。


39
你可能需要添加锚点(例如 ^[0-9]+$ ),否则 abc123def 将被视为一个数字。 - ICR
14
我认为这并不是必需的。matches()仅在从开头到结尾完全匹配时返回true。 - Chthonic Project
4
"^-?\d+.?\d*$" 会比较整个字符串并仅在它是有效数字(包括负数和小数)时匹配。例如,它将匹配 1、10、1.0、-1、-1.0 等。它也会匹配 "1.",但通常可以解析。 - user358089
21
不需要调用 && (text.length() > 2)。 一切都可以在正则表达式模式中检查: if (text.matches("[0-9]{3,}") - ctomek
1
对于不是整数的数字,逗号或点号怎么处理? - nibbana
显示剩余3条评论

24
为了简单地检查字符串是否仅包含字母,请使用以下代码:

为了简单地检查字符串是否仅包含字母,请使用以下代码:

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

为了简单地检查字符串是否仅包含数字,请使用以下代码:

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

希望这能帮助到某些人!


21

这是我会做的方式:

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

$将避免部分匹配,例如:1B


1
我不需要 text.length() > 2 这一部分,因此我只是将 ^[0-9]*$ 替换为 ^[0-9]+$,以确保至少有一个数字。 - Y-B Cause
text.matches("^[0-9]*$")text.matches("[0-9]*") 是相同的。 - Unmitigated

19

8
我认为NumberUtil.isCreatable(String str)不适合用于原问题所要求的内容。例如,NumberUtil.isCreatable("09")返回false,即使"09"仅包含数字。 - Abdull
1
即使 NumberUtils.isCreatable("068907") 返回 false。 - Neeraj Singh

13

从性能上来看,parseInt等解决方案要比其他解决方案差得多,因为它们至少需要异常处理。

我运行了jmh测试,并发现使用charAt迭代字符串并将字符与边界字符进行比较是测试字符串是否仅包含数字的最快方法。

JMH测试

这些测试比较了Character.isDigitPattern.matcher().matchesLong.parseLong与检查字符值的性能。

这些方法对于非ASCII字符串和包含+/-符号的字符串可能会产生不同的结果。

测试以吞吐量模式(越大越好)运行,带有5个预热迭代和5个测试迭代。

结果

请注意,对于第一个测试负载,parseLong几乎比isDigit慢了100倍。

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

测试套件

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

2018年2月23日更新

  • 添加了两个更多的测试案例 - 一个使用 charAt 而不是创建额外的数组,另一个使用 char 代码的 IntStream
  • 在循环测试案例中,如果发现非数字,则立即退出循环
  • 对于循环测试案例中的空字符串,返回 false

2018年2月23日更新

  • 添加了一个更多的测试案例(最快的!),它比较 char 值而不使用流

1
如果您查看toCharArray的代码,它会分配一个char数组并复制字符(我认为这可能很昂贵)。如果您只是使用索引和charAt迭代字符串,那么速度会更快吗?如果您能将Andy的解决方案添加到测试中,那将非常有趣:boolean isNum = text.chars().allMatch(c -> c >= 48 && c <= 57) - Aldo Canepa

8
Apache Commons Lang提供了org.apache.commons.lang.StringUtils.isNumeric(CharSequence cs),它以一个String作为参数并检查其是否完全由数字字符组成(包括非拉丁文字中的数字)。如果存在空格、减号、加号和逗号、点等小数分隔符等字符,则该方法返回false
该类的其他方法允许进一步进行数字检查。

7

使用Java 8的流和lambda表达式的解决方案

String data = "12345";
boolean isOnlyNumbers = data.chars().allMatch(Character::isDigit);

5
StringUtils.isNumeric("1234")

这个运行良好。


如果您使用Apache的StringUtils,您应该谨慎,因为该函数接受的字符不仅限于0-9:例如"१२३"。请参阅https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence- - Matze
如果你使用Apache的StringUtils,你应该小心,因为这个函数接受的字符不仅仅是0-9:例如"१२३"。请参考https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html#isNumeric-java.lang.CharSequence-。 - undefined

3

使用该代码段可以判断文本中的字符是否均为数字,其返回值为布尔型。


2
为了减少神秘数字,您可以按以下方式进行比较:“boolean isNum = text.chars().allMatch(c -> c >= '0' && c <= '9')” - Phe0nix

3
以下正则表达式可用于检查字符串是否仅包含数字: if (str.matches(".*[^0-9].*")) 或 if (str.matches(".*\\D.*")) 如果字符串包含非数字,则上述两个条件都将返回 true。 如果是 false,则表示字符串仅包含数字。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接