253

So I want to iterate for each character in a string.

So I thought:

for (char c : "xyz")

but I get a compiler error:

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

How can I do this?

Frames Catherine White
  • 27,368
  • 21
  • 87
  • 137

9 Answers9

437

The easiest way to for-each every char in a String is to use toCharArray():

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

This gives you the conciseness of for-each construct, but unfortunately String (which is immutable) must perform a defensive copy to generate the char[] (which is mutable), so there is some cost penalty.

From the documentation:

[toCharArray() returns] a newly allocated character array whose length is the length of this string and whose contents are initialized to contain the character sequence represented by this string.

There are more verbose ways of iterating over characters in an array (regular for loop, CharacterIterator, etc) but if you're willing to pay the cost toCharArray() for-each is the most concise.

polygenelubricants
  • 376,812
  • 128
  • 561
  • 623
  • 2
    Will the compiler recognize that a true copy is not needed and apply the appropriate optimizations? – Pacerier Aug 09 '14 at 09:31
  • 1
    @Pacerier No, the current Java compilers will never optimize code. – randers Feb 11 '16 at 20:16
  • 1
    @RAnders00 So, in this case `toCharArray( )` is called 3 times? – denvercoder9 Aug 26 '16 at 15:31
  • @RafiduzzamanSonnet: Well, not entirely. In the comment he said something about the compiler which is the program that turns Java source code (`.java`) into bytecode (`.class`). Modern JVMs (this is what runs your bytecode [aka `.class` and `.jar` files]) *might* be able to optimize this, but I don't think they would do such aggressive optimizations, since that would mean method calls being omitted (which is generally not desirable in running code). – randers Aug 26 '16 at 15:47
  • 3
    With a string length of `211900000`, time taken to complete `for (char c : str.toCharArray()) { }` is ~250ms and time taken to complete `for (char c : charArray) { }` is <10ms. Of course, these time values will depend on the hardware but the takeaway is that one method is significantly costly than the other. – denvercoder9 Aug 26 '16 at 16:12
  • 7
    @RafiduzzamanSonnet: No, the `toCharArray()` is not inside the loop body; it's only called once, and then the loop iterates over that resulting array. (The for-each loop is different than the general `for`-loop, which evaluates the stop-condition each iteration.) – not-just-yeti Sep 05 '16 at 20:10
  • I think this is undesirable solution. The copy-overhead of toCharArray() is unnecessary. – Eugene Chung Sep 11 '19 at 08:16
65
String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}

 

Sebastian Kirsche
  • 861
  • 2
  • 19
  • 36
Matthew Flaschen
  • 278,309
  • 50
  • 514
  • 539
12

Another useful solution, you can work with this string as array of String

for (String s : "xyz".split("")) {
    System.out.println(s);
}
kyxap
  • 516
  • 6
  • 20
  • 5
    Elegant, but unfortunately it doesn't work if any elements of the string being `split()` map to more than one Java character, which is the case for almost all emoticons. For example, this variation of your example will loop four times rather than three: `for (String s : "xz".split("")) { System.out.println(s); }` – skomisa Dec 24 '19 at 20:13
12

If you use Java 8, you can use chars() on a String to get a Stream of characters, but you will need to cast the int back to a char as chars() returns an IntStream.

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

If you use Java 8 with Eclipse Collections, you can use the CharAdapter class forEach method with a lambda or method reference to iterate over all of the characters in a String.

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

This particular example could also use a method reference.

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

Note: I am a committer for Eclipse Collections.

Donald Raab
  • 6,458
  • 2
  • 36
  • 44
8

You need to convert the String object into an array of char using the toCharArray() method of the String class:

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);
}
codaddict
  • 445,704
  • 82
  • 492
  • 529
7

In Java 8 we can solve it as:

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

The method chars() returns an IntStream as mentioned in doc:

Returns a stream of int zero-extending the char values from this sequence. Any char which maps to a surrogate code point is passed through uninterpreted. If the sequence is mutated while the stream is being read, the result is undefined.

Why use forEachOrdered and not forEach ?

The behaviour of forEach is explicitly nondeterministic where as the forEachOrdered performs an action for each element of this stream, in the encounter order of the stream if the stream has a defined encounter order. So forEach does not guarantee that the order would be kept. Also check this question for more.

We could also use codePoints() to print, see this answer for more details.

akhil_mittal
  • 23,309
  • 7
  • 96
  • 95
  • This creates multiple objects, so this answer isn't complete without the caveat that this may be less efficient than a simple indexed loop. – toolforger Nov 10 '18 at 22:20
5

Unfortunately Java does not make String implement Iterable<Character>. This could easily be done. There is StringCharacterIterator but that doesn't even implement Iterator... So make your own:

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++);
            }
        };
    }
}

Now you can (somewhat) easily run for (char c : new CharSequenceCharacterIterable("xyz"))...

Ossifer
  • 51
  • 1
  • 2
3

You can also use a lambda in this case.

    String s = "xyz";
    IntStream.range(0, s.length()).forEach(i -> {
        char c = s.charAt(i);
    });
ander4y748
  • 33
  • 3
-8

For Travers an String you can also use charAt() with the string.

like :

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() is method of string handling in java which help to Travers the string for specific character.

Frames Catherine White
  • 27,368
  • 21
  • 87
  • 137