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

Posted

技术标签:

【中文标题】如何将 for-each 循环应用于字符串中的每个字符?【英文标题】:How do I apply the for-each loop to every character in a String? 【发布时间】:2011-01-27 22:37:03 【问题描述】:

所以我想对字符串中的每个字符进行迭代。

所以我想:

for (char c : "xyz")

但我得到一个编译器错误:

MyClass.java:20: foreach not applicable to expression type

我该怎么做?

【问题讨论】:

【参考方案1】:

如果您使用 Java 8,则可以在 String 上使用 chars() 来获得 Stream 的字符,但您需要将 int 转换回 char,因为 chars() 返回一个IntStream

"xyz".chars().forEach(i -> System.out.print((char)i));

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

Strings.asChars("xyz").forEach(c -> System.out.print(c));

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

Strings.asChars("xyz").forEach(System.out::print)

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

【讨论】:

【参考方案2】:

不幸的是,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++);
            
        ;
    

现在你可以(有点)轻松地运行for (char c : new CharSequenceCharacterIterable("xyz"))...

【讨论】:

【参考方案3】:

Java 8 中我们可以这样解决:

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

chars() 方法返回IntStream,如doc 中所述:

返回一个 int 流,对 char 值进行零扩展 顺序。任何映射到代理代码点的字符都会被传递 通过未解释。如果在流发生时序列发生了突变 正在读取,结果未定义。

为什么使用forEachOrdered 而不是forEach

forEach 的行为是明确的不确定性,因为forEachOrdered 对该流的每个元素执行操作,如果流具有定义的遇到顺序,则按照 流的遇到顺序 .所以forEach 不保证订单会被保留。另请查看question 了解更多信息。

我们也可以使用codePoints() 进行打印,请参阅此answer 了解更多详情。

【讨论】:

这会创建多个对象,所以这个答案是不完整的,但需要注意的是这可能比简单的索引循环效率低。【参考方案4】:

在这种情况下,您也可以使用 lambda。

    String s = "xyz";
    IntStream.range(0, s.length()).forEach(i -> 
        char c = s.charAt(i);
    );

【讨论】:

【参考方案5】:

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

for (String s : "xyz".split("")) 
    System.out.println(s);

【讨论】:

优雅,但不幸的是,如果字符串的任何元素 split() 映射到多个 Java 字符(几乎所有表情符号都是这种情况),它就不起作用。例如,您的示例的这种变体将循环四次而不是三次:for (String s : "x?z".split("")) System.out.println(s); 【参考方案6】:

对于 Travers 一个字符串,您还可以将 charAt() 与字符串一起使用。

喜欢:

String str = "xyz"; // given String
char st = str.charAt(0); // for example we take 0 index element 
System.out.println(st); // print the char at 0 index 

charAt() 是 java 中字符串处理的方法,有助于遍历特定字符的字符串。

【讨论】:

你知道for (char st: "xyz".toCharArray()) 是什么吗? -1 离题(主题:for-each),并使用 charAt 代替 charAT【参考方案7】:
String s = "xyz";
for(int i = 0; i < s.length(); i++)

   char c = s.charAt(i);

 

【讨论】:

OP 期待增强的 for 循环。 投了反对票,因为这不是 OP 所要求的。虽然这是一个有效的解决方案,但它完全不是所要求的 不管 OP 期望什么,我猜这比 for-each 的性能要好。【参考方案8】:

您需要使用 String 类的toCharArray() 方法将 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);

【讨论】:

【参考方案9】:

String 中对每个char 进行for-each 的最简单方法是使用toCharArray()

for (char ch: "xyz".toCharArray()) 

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

来自documentation:

[toCharArray()返回]一个新分配的字符数组,它的长度就是这个字符串的长度,其内容被初始化为包含这个字符串所代表的字符序列。

迭代数组中的字符有更详细的方法(常规 for 循环、CharacterIterator 等),但如果您愿意支付费用,toCharArray() for-each 是最简洁的。

【讨论】:

编译器会认识到不需要真正的副本并应用适当的优化吗? @Pacerier 不,当前的 Java 编译器永远不会优化代码。 @RAnders00 那么,在这种情况下,toCharArray( ) 被调用了 3 次? 如果字符串长度为 211900000,完成 for (char c : str.toCharArray()) 所需的时间约为 250 毫秒,而完成 for (char c : charArray) 所需的时间小于 10 毫秒。当然,这些时间值将取决于硬件,但要点是一种方法比另一种方法成本高得多。 @RafiduzzamanSonnet:不,toCharArray() 不在循环体内;它只被调用一次,然后循环遍历该结果数组。 (for-each 循环不同于一般的 for-loop,后者在每次迭代时评估停止条件。)

以上是关于如何将 for-each 循环应用于字符串中的每个字符?的主要内容,如果未能解决你的问题,请参考以下文章

使用 for-each 循环打印 ArrayList

有没有办法在 XSLT 转换中用应用模板替换 for-each?

如何使For-Each循环向后运行

Java中遍历Map的常用方法

For-Each循环Java错误ArrayIndexOutOfBoundsException

在 for-each 循环中复制动态范围