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

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

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


当前回答

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

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

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

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

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

其他回答

这里有一些专门的类:

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

在Java 8中,我们可以将其求解为:

String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));
str.codePoints().forEachOrdered(i -> System.out.print((char)i));

方法chars()返回doc中提到的IntStream:

返回一个int 0的流,从this扩展char值 序列。将传递映射到代理代码点的任何字符 通过粗略的。如果序列发生突变,而流发生突变 被读取时,结果是未定义的。

方法codePoints()也会根据文档返回一个IntStream:

返回此序列中的代码点值流。任何 序列中遇到的代理项对被组合,就像由 的性格。toCodePoint并将结果传递给流。任何 其他代码单位,包括未配对的普通BMP字符 代理和未定义的代码单元从0扩展到int值 然后传递给流。

字符和码点有什么不同?如本文所述:

Unicode 3.1 added supplementary characters, bringing the total number of characters to more than the 2^16 = 65536 characters that can be distinguished by a single 16-bit char. Therefore, a char value no longer has a one-to-one mapping to the fundamental semantic unit in Unicode. JDK 5 was updated to support the larger set of character values. Instead of changing the definition of the char type, some of the new supplementary characters are represented by a surrogate pair of two char values. To reduce naming confusion, a code point will be used to refer to the number that represents a particular Unicode character, including supplementary ones.

最后,为什么forEachOrdered而不是forEach ?

forEach的行为是显式的不确定的,其中forEachOrdered为流的每个元素执行一个操作,如果流具有定义的遇到顺序,则按照流的遇到顺序执行。因此forEach并不保证顺序会被保持。请检查这个问题以了解更多信息。

关于字符、码位、字形和字素之间的区别,请检查这个问题。

参见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循环。

public class Main {

public static void main(String[] args) {
     String myStr = "Hello";
     String myStr2 = "World";
      
     for (int i = 0; i < myStr.length(); i++) {    
            char result = myStr.charAt(i);
                 System.out.println(result);
     } 
        
     for (int i = 0; i < myStr2.length(); i++) {    
            char result = myStr2.charAt(i);
                 System.out.print(result);              
     }    
   }
}

输出:

H
e
l
l
o
World