Java - 检查STRING是否只包含某些字符的最佳方法是什么?

时间:2014-10-24 19:58:30

标签: java regex string char

我有这个问题:我有String,但我需要确保包含字母 AZ 和数字 0- 9 即可。这是我目前的代码:

boolean valid = true;
for (char c : string.toCharArray()) {
    int type = Character.getType(c);
    if (type == 2 || type == 1 || type == 9) {
        // the character is either a letter or a digit
    } else {
        valid = false;
        break;
    }
}

但实施它的最佳和最有效的方法是什么?

8 个答案:

答案 0 :(得分:14)

因为没有其他人担心"最快"然而,这是我的贡献:

boolean valid = true;

char[] a = s.toCharArray();

for (char c: a)
{
    valid = ((c >= 'a') && (c <= 'z')) || 
            ((c >= 'A') && (c <= 'Z')) || 
            ((c >= '0') && (c <= '9'));

    if (!valid)
    {
        break;
    }
}

return valid;

以下完整的测试代码:

public static void main(String[] args)
{
    String[] testStrings = {"abcdefghijklmnopqrstuvwxyz0123456789", "", "00000", "abcdefghijklmnopqrstuvwxyz0123456789&", "1", "q", "test123", "(#*$))&v", "ABC123", "hello", "supercalifragilisticexpialidocious"};

    long startNanos = System.nanoTime();

    for (String testString: testStrings)
    {
        isAlphaNumericOriginal(testString);
    }

    System.out.println("Time for isAlphaNumericOriginal: " + (System.nanoTime() - startNanos) + " ns"); 

    startNanos = System.nanoTime();

    for (String testString: testStrings)
    {
        isAlphaNumericFast(testString);
    }

    System.out.println("Time for isAlphaNumericFast: " + (System.nanoTime() - startNanos) + " ns");

    startNanos = System.nanoTime();

    for (String testString: testStrings)
    {
        isAlphaNumericRegEx(testString);
    }

    System.out.println("Time for isAlphaNumericRegEx: " + (System.nanoTime() - startNanos) + " ns");

    startNanos = System.nanoTime();

    for (String testString: testStrings)
    {
        isAlphaNumericIsLetterOrDigit(testString);
    }

    System.out.println("Time for isAlphaNumericIsLetterOrDigit: " + (System.nanoTime() - startNanos) + " ns");      
}

private static boolean isAlphaNumericOriginal(String s)
{
    boolean valid = true;
    for (char c : s.toCharArray()) 
    {
        int type = Character.getType(c);
        if (type == 2 || type == 1 || type == 9) 
        {
            // the character is either a letter or a digit
        }
        else 
        {
            valid = false;
            break;
        }
    }

    return valid;
}

private static boolean isAlphaNumericFast(String s)
{
    boolean valid = true;

    char[] a = s.toCharArray();

    for (char c: a)
    {
        valid = ((c >= 'a') && (c <= 'z')) || 
                ((c >= 'A') && (c <= 'Z')) || 
                ((c >= '0') && (c <= '9'));

        if (!valid)
        {
            break;
        }
    }

    return valid;
}

private static boolean isAlphaNumericRegEx(String s)
{
    return Pattern.matches("[\\dA-Za-z]+", s);
}

private static boolean isAlphaNumericIsLetterOrDigit(String s)
{
    boolean valid = true;
    for (char c : s.toCharArray()) { 
        if(!Character.isLetterOrDigit(c))
        {
            valid = false;
            break;
        }
    }
    return valid;
}

为我生成此输出:

Time for isAlphaNumericOriginal: 164960 ns
Time for isAlphaNumericFast: 18472 ns
Time for isAlphaNumericRegEx: 1978230 ns
Time for isAlphaNumericIsLetterOrDigit: 110315 ns

答案 1 :(得分:9)

如果你想避免使用正则表达式,那么Character类可以提供帮助:

boolean valid = true;
for (char c : string.toCharArray()) { 
    if(!Character.isLetterOrDigit(c))
    {
        valid = false;
        break;
    }
}

如果您关心的是大写,那么请在if语句下面执行:

if(!((Character.isLetter(c) && Character.isUpperCase(c)) || Character.isDigit(c)))

答案 2 :(得分:3)

你可以使用Apache Commons Lang:

StringUtils.isAlphanumeric(String)

答案 3 :(得分:3)

除了所有其他答案,这是一个番石榴方法:

boolean valid = CharMatcher.JAVA_LETTER_OR_DIGIT.matchesAllOf(string);

有关CharMatcher的更多信息:https://code.google.com/p/guava-libraries/wiki/StringsExplained#CharMatcher

答案 4 :(得分:2)

使用regular expression

Pattern.matches("[\\dA-Z]+", string)

[\\dA-Z]+:至少出现一次(+)数字或大写字母。

如果您想要包含小写字母,请将[\\dA-Z]+替换为[\\dA-Za-z]+

答案 5 :(得分:2)

以下方法并不像正则表达式那样快,但它是最有效的解决方案之一(我认为),因为它使用非常快的按位运算。

我的解决方案更复杂,更难以阅读和维护,但我认为这是另一种简单的方式来做你想要的。

测试字符串只包含数字或大写字母的好方法是使用表示ASCII表的简单128 bits bitmask(2个长整数)。

因此,对于标准的ASCII表,我们要保留的每个字符都有1个(第48到57位和第65到90位)

因此,您可以测试char是否为:

  1. 带有此掩码的号码:0x3FF000000000000L(如果字符代码<65)
  2. 带有此面具的大写字母:0x3FFFFFFL(如果字符代码&gt; = 65)
  3. 因此以下方法应该有效:

    public boolean validate(String aString) {
        for (int i = 0; i < aString.length(); i++) {
            char c = aString.charAt(i);
    
            if ((c <= 64) & ((0x3FF000000000000L & (1L << c)) == 0) 
                    | (c > 64) & ((0x3FFFFFFL & (1L << (c - 65))) == 0)) {
                return false;
            }
        }
    
        return true;
    }
    

答案 6 :(得分:1)

可维护性和简单性的最佳方式是已发布的正则表达式。熟悉这项技术后,您就会知道会发生什么,如果需要,可以很容易地扩大标准。这是性能的缺点。

最快的方法是使用Array方法。检查字符的数值是否落在想要的范围内ASCII A-Z和0-9几乎是光速。但可维护性很差。简单性消失了。

您可以使用带有char方法的java 7 switch case,但这与第二种情况一样糟糕。

最后,由于我们讨论的是java,我强烈建议使用正则表达式。

答案 7 :(得分:0)

Apache Commons中的StringUtils Lang 3有一个containsOnly方法,https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/StringUtils.html

实施应该足够快。