Java-分裂字符串,是字母数字

时间:2014-12-22 02:25:36

标签: java string split

示例输入:

RC23
CC23QQ21HD32
BPOASDf91A5HH123

示例输出:

[RC,23]
[CC,23,QQ,21,HD,32]
[BPOASDf,91,A,5,HH,123]

alpha部分和数字部分的长度不固定。

我知道如何将split()与//.' ' ' '([a-z])这样的正则表达式一起使用,但是虽然我检查了split() Java API但我找不到任何可以帮助我解决这个问题的东西。

有没有办法使用split()来执行此操作?或者我需要使用另一种方法来分割这些字符串。

任何帮助都将不胜感激。

3 个答案:

答案 0 :(得分:4)

试试这个正则表达式:"((?<=[a-zA-Z])(?=[0-9]))|((?<=[0-9])(?=[a-zA-Z]))"

这是一个正在运行的示例:http://ideone.com/c02rmM

{
    ...
    String someString = "CC23QQ21HD32";
    String regex = "((?<=[a-zA-Z])(?=[0-9]))|((?<=[0-9])(?=[a-zA-Z]))";
    System.out.println(Arrays.asList(someString.split(regex)));
    //outputs [CC, 23, QQ, 21, HD, 32]
    ...
}

正则表达式使用预测 (?=ValueToMatch)查看背后 (?<=ValueToMatch)

它的前半部分(在|之前)询问:&#34;前一个字符是否为(?<=[a-zA-Z])字母?下一个字符是数字(?=[0-9])吗?&#34;如果两者都为真,则它将字符串与正则表达式匹配。

该正则表达式的后半部分是相反的。它问:&#34;前一个字符是数字(?<=[0-9])?下一个字符是字母吗? (?=[a-zA-Z])&#34;,如果两者都属实,它将再次匹配。

通常split()会删除正则表达式匹配的字符。即使对于这个正则表达式,这仍然是正确的。但是,由于正则表达式匹配0宽度前瞻,因此不会删除您正在寻找的实际字符。

查看Adam Paynter的答案,了解更多关于 lookaheads 了解背后的信息:how to split string with some separator but without removing that separator in Java?

答案 1 :(得分:1)

您可以匹配1个或多个连续的字母字符或1个或多个连续的数字字符。一旦序列中断停止匹配,则存储序列然后重新开始。非字字符将被完全忽略。

修改:我在下面创建了一个简单的性能测试,以显示使用String.split()Pattern.matcher()之间的速度。拆分版本比匹配器+循环版本快2.5倍。

解决方案

private static String[] splitAlphaNumeric(String str) {
    return str.split("(?i)((?<=[A-Z])(?=\\d))|((?<=\\d)(?=[A-Z]))");
}

实施例

import java.util.*;
import java.util.regex.*;

public class SplitAlphaNumeric {
    private static final Pattern ALPH_NUM_PAT = Pattern.compile("[0-9]+|[A-Z]+");

    private static List<String> input = Arrays.asList(
        "RC23",
        "CC23QQ21HD32",
        "BPOASDf91A5HH123"
    );

    public static void main(String[] args) {
        System.out.printf("Execution time: %dns%n", testMatch());
        System.out.printf("Execution time: %dns%n", testSplit());
    }

    public static long testMatch() {
        System.out.println("Begin Test 1...");
        long start = System.nanoTime();
        for (String str : input) {
            System.out.printf("%-16s -> %s%n", str, parse(str));
        }
        long end = System.nanoTime();
        return end - start;
    }

    public static long testSplit() {
        System.out.println("\nBegin Test 2...");
        long start = System.nanoTime();
        for (String str : input) {
            System.out.printf("%-16s -> %s%n", str, parse2(str));
        }
        long end = System.nanoTime();
        return end - start;
    }

    private static List<String> parse(String str) {
        List<String> parts = new LinkedList<String>();
        Matcher matcher = ALPH_NUM_PAT.matcher(str);
        while (matcher.find()) {
            parts.add(matcher.group());
        }
        return parts;
    }

    private static List<String> parse2(String str) {
        return Arrays.asList(str.split("(?i)((?<=[A-Z])(?=\\d))|((?<=\\d)(?=[A-Z]))"));
    }
}

输出

Begin Test 1...
RC23             -> [RC, 23]
CC23QQ21HD32     -> [CC, 23, QQ, 21, HD, 32]
BPOASDf91A5HH123 -> [BPOASD, 91, A, 5, HH, 123]
Execution time: 4879125ns

Begin Test 2...
RC23             -> [RC, 23]
CC23QQ21HD32     -> [CC, 23, QQ, 21, HD, 32]
BPOASDf91A5HH123 -> [BPOASDf, 91, A, 5, HH, 123]
Execution time: 1953349ns

答案 2 :(得分:0)

您可以使用前瞻,例如&#34; ((?<=%1[0-9]+)|(?=%1[0-9]+))&#34;