Java中最高效的字符串分割方法是什么?

11
为了回答这个问题,我们假设我有一个包含值为Two;.Three;.Four(等等)的String,但是这些元素是由;.分隔的。现在我知道有多种拆分字符串的方法,例如split()StringTokenizer(后者速度更快且效果良好),但我的输入文件大约有1GB,我正在寻找比StringTokenizer稍微更高效的方法。经过一些研究,我发现indexOfsubstring非常高效,但示例仅具有单个分隔符或结果仅返回单个单词/元素。使用indexOfsubstring的示例代码:
String s = "quick,brown,fox,jumps,over,the,lazy,dog";
int from = s.indexOf(',');
int to = s.indexOf(',', from+1);
String brown = s.substring(from+1, to);

上述方法适用于打印brown,但我如何使用indexOfsubstring来拆分带有多个分隔符的行,并将所有项按如下方式显示。

预期输出

Two
Three
Four
....and so on

1
你想要达到什么目的?你已经对各种测试用例进行了测试,看哪个更“高效”了吗? - Buhake Sindi
还有一个indexOf重载,它接受String类型的参数... - yshavit
@BuhakeSindi 是的,我已经进行了测试。在我的机器上使用StringTokenizer处理一个样本字符串需要8.0微秒,而使用split()则需要23微秒。 - user92038111111
1
只需循环,indexOf()函数需要一个起始参数,该参数应为上次找到的索引。 - eckes
@AvinashRaj,如果我想使用每个元素,那就不是很灵活了。 - user92038111111
显示剩余2条评论
3个回答

7

这是我用于拆分大型(1GB+)制表符分隔文件的方法。它仅限于使用char分隔符,以避免额外的方法调用开销(可能会被运行时优化掉),但可以轻松转换为字符串分隔符。如果有人能想出更快的方法或改进此方法,我会很感兴趣。

public static String[] split(final String line, final char delimiter)
{
    CharSequence[] temp = new CharSequence[(line.length() / 2) + 1];
    int wordCount = 0;
    int i = 0;
    int j = line.indexOf(delimiter, 0); // first substring

    while (j >= 0)
    {
        temp[wordCount++] = line.substring(i, j);
        i = j + 1;
        j = line.indexOf(delimiter, i); // rest of substrings
    }

    temp[wordCount++] = line.substring(i); // last substring

    String[] result = new String[wordCount];
    System.arraycopy(temp, 0, result, 0, wordCount);

    return result;
}

你可以进一步改进这个程序,通过一次性获取所有索引,因为indexOf会遍历整个字符串。 - Sport
在循环内,我从上一个出现的索引(line.indexOf(delimiter, i))开始每次搜索,这样每个字符只被检查一次。我可能可以编写indexOf(char, int)的内联版本,以避免重复方法调用的开销。 - Parker

5

如果你想要最高效的处理方式,我不会使用Strings,更不要去拆分它们。我会像编译器一样逐个字符地处理文件。使用一个带有大缓冲区(比如128kb)的BufferedReader,每次读取一个char,将它们累积到StringBuilder中,直到遇到;或行终止符。


好的,我会尝试并回报。谢谢。 - user92038111111
@AvinashRaj,你的评论与我的答案无关。请不要在这里发布无关的评论。 - user207421
@AvinashRaj 这与我的答案和你之前的评论没有任何关系。 - user207421

4
< p > StringTokenizerStringBuilder 更快。 < /p >
public static void main(String[] args) {

    String str = "This is String , split by StringTokenizer, created by me";
    StringTokenizer st = new StringTokenizer(str);

    System.out.println("---- Split by space ------");
    while (st.hasMoreElements()) {
        System.out.println(st.nextElement());
    }

    System.out.println("---- Split by comma ',' ------");
    StringTokenizer st2 = new StringTokenizer(str, ",");

    while (st2.hasMoreElements()) {
        System.out.println(st2.nextElement());
    }
}

3
根据JDK文档StringTokenizer类已被认为是一个遗留类。建议使用String.split或者java.util.regex包中的其他类。 - Yonathan W'Gebriel

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