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

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

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


当前回答

所以通常有两种方法在java中迭代字符串,这已经被很多人在这个线程中回答了,只是添加了我的版本 首先是使用

String s = sc.next() // assuming scanner class is defined above
for(int i=0; i<s.length(); i++){
     s.charAt(i)   // This being the first way and is a constant time operation will hardly add any overhead
  }

char[] str = new char[10];
str = s.toCharArray() // this is another way of doing so and it takes O(n) amount of time for copying contents from your string class to the character array

如果性能受到威胁,那么我会建议在常数时间内使用第一个,如果不是,那么考虑到java中字符串类的不可变性,那么使用第二个会使您的工作更容易。

其他回答

StringTokenizer完全不适合将字符串分解为单个字符的任务。使用String#split(),你可以通过使用一个不匹配的正则表达式轻松做到这一点,例如:

String[] theChars = str.split("|");

但是StringTokenizer不使用正则表达式,并且没有可以指定的分隔符字符串来匹配字符之间的空白。你可以使用一个可爱的小技巧来完成同样的事情:使用字符串本身作为分隔符字符串(使其中的每个字符都成为分隔符),并让它返回分隔符:

StringTokenizer st = new StringTokenizer(str, str, true);

但是,我只是为了排除它们而提到这些选项。这两种技术都将原始字符串分解为单字符字符串,而不是char原语,并且都以对象创建和字符串操作的形式涉及大量开销。与在for循环中调用charAt()相比,后者几乎没有开销。

如果你需要遍历字符串的代码点(见这个答案),一个更短/更可读的方法是使用Java 8中添加的CharSequence#codePoints方法:

for(int c : string.codePoints().toArray()){
    ...
}

或者直接使用流而不是for循环:

string.codePoints().forEach(c -> ...);

如果你想要字符流,还有CharSequence#chars(尽管它是IntStream,因为没有CharStream)。

所以通常有两种方法在java中迭代字符串,这已经被很多人在这个线程中回答了,只是添加了我的版本 首先是使用

String s = sc.next() // assuming scanner class is defined above
for(int i=0; i<s.length(); i++){
     s.charAt(i)   // This being the first way and is a constant time operation will hardly add any overhead
  }

char[] str = new char[10];
str = s.toCharArray() // this is another way of doing so and it takes O(n) amount of time for copying contents from your string class to the character array

如果性能受到威胁,那么我会建议在常数时间内使用第一个,如果不是,那么考虑到java中字符串类的不可变性,那么使用第二个会使您的工作更容易。

我同意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");

两个选项

for(int i = 0, n = s.length() ; i < n ; i++) { 
    char c = s.charAt(i); 
}

or

for(char c : s.toCharArray()) {
    // process c
}

第一种可能更快,第二种可能更易读。