Como aplico o loop for-each a todos os caracteres em uma String?

189

Então, eu quero iterar para cada caractere em uma string.

Então eu pensei:

for (char c : "xyz")

mas recebo um erro do compilador:

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

Como posso fazer isso?

Lyndon White
fonte

Respostas:

333

A maneira mais fácil de cada um de cada charum Stringé usar toCharArray():

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

Isso fornece a concisão de cada construção, mas infelizmente String(que é imutável) deve executar uma cópia defensiva para gerar a char[](que é mutável), para que haja alguma penalidade de custo.

A partir da documentação :

[ toCharArray()retorna] uma matriz de caracteres recém-alocada cujo comprimento é o comprimento dessa sequência e cujo conteúdo é inicializado para conter a sequência de caracteres representada por essa sequência.

Existem maneiras mais detalhadas de iterar os caracteres em uma matriz (regular para loop CharacterIterator, etc.), mas se você estiver disposto a pagar o custo toCharArray()de cada uma delas, é a mais concisa.

poligenelubricants
fonte
1
O compilador reconhecerá que uma cópia verdadeira não é necessária e aplicará as otimizações apropriadas?
Pacerier 9/08/14
1
@Pacerier Não, os compiladores Java atuais nunca otimizarão o código.
RAnders00
1
@ RAnders00 Então, neste caso, toCharArray( )é chamado 3 vezes?
denvercoder9
1
Com um comprimento de seqüência de caracteres 211900000, o tempo necessário para concluir for (char c : str.toCharArray()) { }é de ~ 250ms e o tempo necessário para concluir for (char c : charArray) { }é <10ms. Obviamente, esses valores de tempo dependerão do hardware, mas a conclusão é que um método é significativamente caro que o outro.
Denvercoder9
7
@RafiduzzamanSonnet: Não, o toCharArray()não está dentro do corpo do loop; é chamado apenas uma vez e, em seguida, o loop itera sobre a matriz resultante. (A-para cada circuito é diferente do que a geral for-loop, que avalia a condição de paragem-cada iteração.)
não-just-yeti
50
String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}

 

Matthew Flaschen
fonte
7
O OP espera um loop for inalterado.
AmitG
3
A votação foi baixa porque esse não é o pedido específico do OP. Embora esta seja uma solução válida é totalmente não o que está sendo solicitado
Sirens
1
Não importa o que o OP esperasse, isso tem melhor desempenho do que para cada um, eu acho.
Eric Wang
9

Outra solução útil, você pode trabalhar com essa string como matriz de String

for (String s : "xyz".split("")) {
    System.out.println(s);
}
kyxap
fonte
Elegante, mas infelizmente não funciona se algum elemento da string sendo split()mapeado para mais de um caractere Java, o que é o caso de quase todos os emoticons. Por exemplo, essa variação do seu exemplo será for (String s : "x😁z".split("")) { System.out.println(s); }
repetida
5

Você precisa converter o objeto String em uma matriz de caracteres usando o toCharArraymétodo () da classe String:

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
fonte
4

No Java 8 , podemos resolvê-lo da seguinte maneira:

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

O método chars () retorna um IntStreamcomo mencionado no doc :

Retorna um fluxo de int estendendo zero os valores de caracteres dessa sequência. Qualquer caractere mapeado para um ponto de código substituto é passado não interpretado. Se a sequência for alterada enquanto o fluxo estiver sendo lido, o resultado será indefinido.

Por que usar forEachOrderede não forEach?

O comportamento de forEaché explicitamente não determinístico, onde, quando ele forEachOrderedexecuta uma ação para cada elemento desse fluxo, na ordem de encontro do fluxo, se o fluxo tiver uma ordem de encontro definida. Portanto forEach, não garante que o pedido seja mantido. Verifique também esta pergunta para mais informações.

Também poderíamos usar codePoints()para imprimir; consulte esta resposta para obter mais detalhes.

akhil_mittal
fonte
Isso cria vários objetos; portanto, essa resposta não é completa sem a ressalva de que isso pode ser menos eficiente do que um simples loop indexado.
toolforger
4

Infelizmente o Java não faz Stringimplementar Iterable<Character>. Isso poderia ser feito facilmente. Existe, StringCharacterIteratormas isso nem sequer implementa Iterator... Então faça o seu:

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

Agora você pode (um pouco) facilmente executar for (char c : new CharSequenceCharacterIterable("xyz"))...

Ossifer
fonte
3

Se você usa o Java 8, pode usar chars()no Stringpara obter um número Streamde caracteres, mas precisará intretroceder para a charcomo chars()retorna um IntStream.

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

Se você usar Java 8 com Eclipse Collections , poderá usar o método de CharAdapterclasse forEachcom uma referência lambda ou method para iterar sobre todos os caracteres em a String.

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

Este exemplo específico também pode usar uma referência de método.

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

Nota: Sou um colaborador das Coleções Eclipse.

Donald Raab
fonte
1

Você também pode usar um lambda neste caso.

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

Para Travers uma String, você também pode usar charAt()com a string.

gostar :

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() é um método de manipulação de string em java que ajuda a rastrear a string para caracteres específicos.

user1690439
fonte
2
você sabe o que for (char st: "xyz".toCharArray()) {}é?
AmitG
Isso não será compilado.
Maron
-1 fora do tópico (tópico: para-cada), e da utilização, em vez de charAt charAt
peenut