如何将for-each循环应用于String中的每个字符?

Lyn*_*ite 176 java string foreach loops char

所以我想迭代字符串中的每个字符.

所以我认为:

for (char c : "xyz")
Run Code Online (Sandbox Code Playgroud)

但是我收到编译错误:

MyClass.java:20: foreach not applicable to expression type
Run Code Online (Sandbox Code Playgroud)

我怎样才能做到这一点?

pol*_*nts 315

为,每每最简单的方法char在一个String是使用toCharArray():

for (char ch: "xyz".toCharArray()) {
}
Run Code Online (Sandbox Code Playgroud)

这为您提供了for-each构造的简洁性,但不幸的是String(这是不可变的)必须执行防御性副本来生成char[](这是可变的),因此存在一些成本损失.

文档:

[ toCharArray()returns] 一个新分配的字符数组,其长度为该字符串的长度,其内容初始化为包含该字符串表示的字符序列.

有更多冗长的方法来迭代数组中的字符(常规循环CharacterIterator等),但如果你愿意支付成本toCharArray()- 每个都是最简洁的.

  • @RafiduzzamanSonnet:不,`toCharArray()`不在循环体内; 它只被调用一次,然后循环遍历生成的数组.(for-each循环不同于一般的`for`循环,它会在每次迭代时评估停止条件.) (6认同)
  • 对于字符串长度为“211900000”的情况,完成“for (char c : str.toCharArray()) { }”所需的时间约为 250 毫秒,完成“for (char c : charArray) { }”所需的时间 <10 毫秒。当然,这些时间值取决于硬件,但结论是一种方法比另一种方法成本要高得多。 (3认同)
  • 编译器是否会认识到不需要真实副本并应用适当的优化? (2认同)

Mat*_*hen 48

String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}
Run Code Online (Sandbox Code Playgroud)

 

  • OP期望为循环增强. (7认同)
  • 投票结果是因为这特别不是OP所要求的.虽然这是一个有效的解决方案,但它完全不是被问到的 (3认同)
  • 无论 OP 期望什么,我猜这都比 for-each 具有更好的性能。 (2认同)

Don*_*aab 7

如果您使用 Java 8,则可以使用chars()on aString来获取 aStream字符,但您需要将其转换int回 achar作为chars()返回 an IntStream

"xyz".chars().forEach(i -> System.out.print((char)i));
Run Code Online (Sandbox Code Playgroud)

如果您将 Java 8 与Eclipse Collections 一起使用,您可以使用带有 lambda 或方法引用的CharAdapterforEach方法来迭代String.

Strings.asChars("xyz").forEach(c -> System.out.print(c));
Run Code Online (Sandbox Code Playgroud)

这个特定的例子也可以使用方法引用。

Strings.asChars("xyz").forEach(System.out::print)
Run Code Online (Sandbox Code Playgroud)

注意:我是 Eclipse Collections 的提交者。


kyx*_*xap 6

另一个有用的解决方案,您可以使用此字符串作为String数组

for (String s : "xyz".split("")) {
    System.out.println(s);
}
Run Code Online (Sandbox Code Playgroud)

  • 很优雅,但不幸的是,如果“split()”字符串的任何元素映射到多个 Java 字符(几乎所有表情符号都是这种情况),则它不起作用。例如,示例的这种变体将循环四次而不是三次:`for (String s : "xz".split("")) { System.out.println(s); }` (2认同)

cod*_*ict 5

您需要使用toCharArrayString类的()方法将String对象转换为char数组:

String str = "xyz";
char arr[] = str.toCharArray(); // convert the String object to array of char

// iterate over the array using the for-each loop.       
for(char c: arr){
    System.out.println(c);
}
Run Code Online (Sandbox Code Playgroud)


i_a*_*ero 5

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

String str = "xyz";
str.chars().forEachOrdered(i -> System.out.print((char)i));    
Run Code Online (Sandbox Code Playgroud)

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

返回一个 int 流,零扩展此序列中的 char 值。映射到代理代码点的任何字符都未经解释地传递。如果在读取流时序列发生变异,则结果未定义。

为什么使用forEachOrdered而不是forEach

的行为forEach是明确地不确定性,其中作为forEachOrdered执行用于该流的每个元件的操作,在该流的遭遇顺序如果流具有规定的遭遇顺序。所以forEach不保证订单会被保留。另请查看此问题以获取更多信息。

我们也可以codePoints()用于打印,有关更多详细信息,请参阅此答案


小智 5

不幸的是Java没有String实现Iterable<Character>。这很容易做到。有StringCharacterIterator,但甚至没有实现Iterator......所以让你自己的:

public class CharSequenceCharacterIterable implements Iterable<Character> {
    private CharSequence cs;

    public CharSequenceCharacterIterable(CharSequence cs) {
        this.cs = cs;
    }

    @Override
    public Iterator<Character> iterator() {
        return new Iterator<Character>() {
            private int index = 0;

            @Override
            public boolean hasNext() {
                return index < cs.length();
            }

            @Override
            public Character next() {
                return cs.charAt(index++);
            }
        };
    }
}
Run Code Online (Sandbox Code Playgroud)

现在你可以(在某种程度上)轻松地运行for (char c : new CharSequenceCharacterIterable("xyz"))......