在Java中迭代字符串字符的方法有:

使用StringTokenizer ? 将String转换为char[]并对其进行迭代。

最简单/最好/最正确的迭代方法是什么?


当前回答

这里有一些专门的类:

import java.text.*;

final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
   // process c
   ...
}

其他回答

我同意StringTokenizer在这里是多余的。事实上,我尝试了上面的建议,并花了时间。

我的测试相当简单:创建一个带有大约一百万个字符的StringBuilder,将其转换为String,并在转换为char数组/使用CharacterIterator一千次之后使用charAt()遍历每个字符(当然要确保对字符串做一些事情,这样编译器就不能优化掉整个循环:-))。

在2.6 GHz的Powerbook(那是mac:-))和JDK 1.5上的结果:

测试1:charAt +字符串——> 3138msec 测试2:字符串转换为数组——> 9568msec 测试3:StringBuilder charAt——> 3536msec 测试4:CharacterIterator和String——> 12151msec

由于结果明显不同,最直接的方法似乎也是最快的方法。有趣的是,StringBuilder的charAt()似乎比String的charAt()稍慢。

顺便说一句,我建议不要使用CharacterIterator,因为我认为它滥用'\uFFFF'字符作为“迭代结束”是一个非常糟糕的hack。在大型项目中,总是有两个人为了两个不同的目的使用同一种黑客,代码就会神秘地崩溃。

下面是其中一个测试:

    int count = 1000;
    ...

    System.out.println("Test 1: charAt + String");
    long t = System.currentTimeMillis();
    int sum=0;
    for (int i=0; i<count; i++) {
        int len = str.length();
        for (int j=0; j<len; j++) {
            if (str.charAt(j) == 'b')
                sum = sum + 1;
        }
    }
    t = System.currentTimeMillis()-t;
    System.out.println("result: "+ sum + " after " + t + "msec");

如果需要性能,那么必须在环境中进行测试。没有别的办法。

下面是示例代码:

int tmp = 0;
String s = new String(new byte[64*1024]);
{
    long st = System.nanoTime();
    for(int i = 0, n = s.length(); i < n; i++) {
        tmp += s.charAt(i);
    }
    st = System.nanoTime() - st;
    System.out.println("1 " + st);
}

{
    long st = System.nanoTime();
    char[] ch = s.toCharArray();
    for(int i = 0, n = ch.length; i < n; i++) {
        tmp += ch[i];
    }
    st = System.nanoTime() - st;
    System.out.println("2 " + st);
}
{
    long st = System.nanoTime();
    for(char c : s.toCharArray()) {
        tmp += c;
    }
    st = System.nanoTime() - st;
    System.out.println("3 " + st);
}
System.out.println("" + tmp);

在Java网上,我得到:

1 10349420
2 526130
3 484200
0

在Android x86 API 17上,我得到:

1 9122107
2 13486911
3 12700778
0

参见Java教程:字符串。

public class StringDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";
        int len = palindrome.length();
        char[] tempCharArray = new char[len];
        char[] charArray = new char[len];

        // put original string in an array of chars
        for (int i = 0; i < len; i++) {
            tempCharArray[i] = palindrome.charAt(i);
        } 

        // reverse array of chars
        for (int j = 0; j < len; j++) {
            charArray[j] = tempCharArray[len - 1 - j];
        }

        String reversePalindrome =  new String(charArray);
        System.out.println(reversePalindrome);
    }
}

将长度放入int len并使用for循环。

这里有一些专门的类:

import java.text.*;

final CharacterIterator it = new StringCharacterIterator(s);
for(char c = it.first(); c != CharacterIterator.DONE; c = it.next()) {
   // process c
   ...
}

注意,如果处理BMP (Unicode基本多语言平面)之外的字符,即u0000-uFFFF范围之外的代码点,则此处描述的大多数其他技术都将失效。这种情况很少发生,因为在此之外的代码点大多分配给了死语言。但除此之外还有一些有用的字符,例如一些用于数学符号的代码点,以及一些用于编码中文专有名称的代码点。

在这种情况下,你的代码将是:

String str = "....";
int offset = 0, strLen = str.length();
while (offset < strLen) {
  int curChar = str.codePointAt(offset);
  offset += Character.charCount(curChar);
  // do something with curChar
}

Character.charCount(int)方法需要Java 5+。

来源:http://mindprod.com/jgloss/codepoint.html