¿Cómo aplico el ciclo for-each a cada personaje de una cadena?

189

Entonces quiero iterar para cada carácter en una cadena.

Así que pensé:

for (char c : "xyz")

pero me sale un error del compilador:

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

¿Cómo puedo hacer esto?

Lyndon White
fuente

Respuestas:

333

La forma más fácil de cada uno charen cada Stringes usar toCharArray():

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

Esto le da la concisión de cada construcción, pero desafortunadamente String(que es inmutable) debe realizar una copia defensiva para generar char[](que es mutable), por lo que hay una penalización de costos.

De la documentación :

[ toCharArray()devuelve] una matriz de caracteres recientemente asignada cuya longitud es la longitud de esta cadena y cuyo contenido se inicializa para contener la secuencia de caracteres representada por esta cadena.

Hay formas más detalladas de iterar sobre los caracteres en una matriz (regular for loop CharacterIterator, etc.) pero si está dispuesto a pagar el costo toCharArray(), cada uno es el más conciso.

poligenelubricantes
fuente
1
¿El compilador reconocerá que no se necesita una copia verdadera y aplicará las optimizaciones apropiadas?
Pacerier
1
@Pacerier No, los compiladores de Java actuales nunca optimizarán el código.
RAnders00
1
@ RAnders00 Entonces, ¿en este caso toCharArray( )se llama 3 veces?
denvercoder9
1
Con una longitud de cadena de 211900000, el tiempo necesario para completar for (char c : str.toCharArray()) { }es ~ 250 ms y el tiempo necesario para completar for (char c : charArray) { }es <10 ms. Por supuesto, estos valores de tiempo dependerán del hardware, pero la conclusión es que un método es significativamente costoso que el otro.
denvercoder9
77
@RafiduzzamanSonnet: No, toCharArray()no está dentro del cuerpo del bucle; solo se llama una vez, y luego el ciclo itera sobre esa matriz resultante. (El bucle for-each es diferente al bucle general for, que evalúa la condición de parada en cada iteración).
not-just-yeti
50
String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}

 

Matthew Flaschen
fuente
77
OP espera inhalado para el bucle.
AmitG
3
Down votó porque esto no es específicamente lo que OP solicitó. Si bien esta es una solución válida, no es totalmente lo que se pide
sirenas
1
No importa lo que espere el OP, esto tiene un mejor rendimiento que para cada uno, supongo.
Eric Wang
9

Otra solución útil, puede trabajar con esta cadena como una matriz de cadenas

for (String s : "xyz".split("")) {
    System.out.println(s);
}
kyxap
fuente
Elegante, pero desafortunadamente no funciona si algún elemento de la cadena se split()asigna a más de un carácter Java, como es el caso de casi todos los emoticones. Por ejemplo, esta variación de su ejemplo se repetirá cuatro veces en lugar de tres:for (String s : "x😁z".split("")) { System.out.println(s); }
skomisa
5

Debe convertir el objeto String en una matriz de caracteres utilizando el toCharArraymétodo () de la clase 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);
}
codictorio
fuente
4

En Java 8 podemos resolverlo como:

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

El método chars () devuelve un IntStreamcomo se menciona en doc :

Devuelve una secuencia de int cero que extiende los valores de caracteres de esta secuencia. Cualquier carácter que se asigne a un punto de código sustituto se pasa sin interpretación. Si la secuencia está mutada mientras se lee la secuencia, el resultado no está definido.

¿Por qué usar forEachOrderedy no forEach?

El comportamiento de forEaches explícitamente no determinista donde, a medida que forEachOrderedrealiza una acción para cada elemento de esta secuencia, en el orden de encuentro de la secuencia si la secuencia tiene un orden de encuentro definido. Por forEachlo tanto , no garantiza que se mantenga el pedido. También revise esta pregunta para más.

También podríamos usar codePoints()para imprimir, vea esta respuesta para más detalles.

akhil_mittal
fuente
Esto crea múltiples objetos, por lo que esta respuesta no está completa sin la advertencia de que esto puede ser menos eficiente que un simple bucle indexado.
Toolforger
4

Desafortunadamente Java no hace Stringimplementar Iterable<Character>. Esto podría hacerse fácilmente. Hay StringCharacterIteratorpero eso ni siquiera se implementa Iterator... Así que haga el suyo:

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

Ahora puedes ejecutar (algo) fácilmente for (char c : new CharSequenceCharacterIterable("xyz"))...

Ossifer
fuente
3

Si usa Java 8, puede usarlo chars()en a Stringpara obtener un número Streamde caracteres, pero deberá convertir la parte intposterior en unchar como chars()devuelve un IntStream.

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

Si usa Java 8 con Eclipse Collections , puede usar la CharAdapterclaseforEach método de con una referencia lambda o método para iterar sobre todos los caracteres en a String.

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

Este ejemplo particular también podría usar una referencia de método.

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

Nota: Soy un committer para Eclipse Collections.

Donald Raab
fuente
1

También puede usar una lambda en este caso.

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

Para Travers an String también puede usar charAt()con la cadena.

me gusta :

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() es un método de manejo de cadenas en Java que ayuda a atravesar la cadena para un carácter específico.

usuario1690439
fuente
2
sabes que for (char st: "xyz".toCharArray()) {}es
AmitG
Esto no se compilará.
Maroun
-1 fuera de tema (tema: para cada uno), y use charAt en lugar de charAT
peenut