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

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

所以我想:

for (char c : "xyz")

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

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

我该怎么做?

【问题讨论】:

    标签: java string loops foreach char


    【解决方案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,后者在每次迭代时评估停止条件。)
            猜你喜欢
            • 2021-08-31
            • 1970-01-01
            • 2021-09-28
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-02-19
            • 2021-06-26
            • 2019-02-04
            相关资源
            最近更新 更多