Come posso applicare il ciclo for-each a tutti i personaggi di una stringa?


189

Quindi voglio iterare per ogni personaggio in una stringa.

Quindi ho pensato:

for (char c : "xyz")

ma ottengo un errore del compilatore:

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

Come posso fare questo?

Risposte:


333

Il modo più semplice per ogni utente charin a Stringè utilizzare toCharArray():

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

Questo ti dà la concisione di per ogni costrutto, ma sfortunatamente String(che è immutabile) deve eseguire una copia difensiva per generare ilchar[] (che è mutabile), quindi c'è una penalità di costo.

Dalla documentazione :

[ toCharArray()restituisce] una matrice di caratteri appena allocata la cui lunghezza è la lunghezza di questa stringa e il cui contenuto è inizializzato per contenere la sequenza di caratteri rappresentata da questa stringa.

Esistono modi più dettagliati per scorrere i caratteri in un array (normale per loop CharacterIterator, ecc.) Ma se sei disposto a pagare il costo toCharArray()per ognuno di essi è il più conciso.


1
Il compilatore riconoscerà che non è necessaria una copia vera e applicherà le ottimizzazioni appropriate?
Pacerier,

1
@Pacerier No, gli attuali compilatori Java non ottimizzeranno mai il codice.
RAnders00,

1
@ RAnders00 Quindi, in questo caso toCharArray( )viene chiamato 3 volte?
denvercoder9,

1
Con una lunghezza della stringa di 211900000, il tempo impiegato per il completamento for (char c : str.toCharArray()) { }è ~ 250 ms e il tempo impiegato per il completamento for (char c : charArray) { }è <10 ms. Naturalmente, questi valori temporali dipenderanno dall'hardware, ma il metodo da asporto è che un metodo è significativamente costoso rispetto all'altro.
denvercoder9,

7
@RafiduzzamanSonnet: No, toCharArray()non è all'interno del corpo del loop; viene chiamato solo una volta, quindi il ciclo scorre sull'array risultante. (Il ciclo for-each è diverso dal generale for-loop, che valuta ogni condizione di stop per ogni iterazione.)
not-just-yeti

50
String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}

 


7
OP si aspetta che sia cambiato per il loop.
AmitG

3
Down ha votato perché questo non è specificamente ciò che l'OP ha richiesto. Sebbene questa sia una soluzione valida, non è del tutto ciò che viene chiesto
Sirene,

1
Indipendentemente da ciò che l'OP si aspettava, questo ha prestazioni migliori di quelle per cui credo.
Eric Wang,

9

Un'altra soluzione utile, puoi lavorare con questa stringa come matrice di String

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

Elegante, ma sfortunatamente non funziona se alcuni elementi della stringa sono split()associati a più di un personaggio Java, come nel caso di quasi tutte le emoticon. Ad esempio, questa variazione del tuo esempio verrà ripetuta quattro volte anziché tre:for (String s : "x😁z".split("")) { System.out.println(s); }
skomisa

5

Devi convertire l'oggetto String in un array di caratteri usando il toCharArraymetodo () della 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);
}

4

In Java 8 possiamo risolverlo come:

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

Il metodo chars () restituisce un IntStreamcome menzionato nel doc :

Restituisce un flusso di int zero che estende i valori char da questa sequenza. Qualsiasi carattere associato a un punto di codice surrogato viene passato senza interpretazione. Se la sequenza viene modificata durante la lettura dello stream, il risultato non è definito.

Perché usare forEachOrderede no forEach?

Il comportamento di forEachè esplicitamente non deterministico dove come forEachOrderedesegue un'azione per ciascun elemento di questo flusso, nell'ordine di incontro del flusso se il flusso ha un ordine di incontro definito. Quindi forEachnon garantisce che l'ordine verrà mantenuto. Controlla anche questa domanda per ulteriori informazioni.

Potremmo anche usare codePoints()per stampare, vedere questa risposta per maggiori dettagli.


Questo crea più oggetti, quindi questa risposta non è completa senza la precisazione che potrebbe essere meno efficiente di un semplice ciclo indicizzato.
Toolforger,

4

Purtroppo Java non crea Stringattrezzo Iterable<Character>. Questo potrebbe essere facilmente fatto. C'è StringCharacterIteratorma questo non implementa nemmeno Iterator... Quindi creane uno tuo:

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

Ora puoi (in qualche modo) facilmente eseguire for (char c : new CharSequenceCharacterIterable("xyz"))...


3

Se si utilizza Java 8, è possibile utilizzare chars()su a Stringper ottenere una Streamdi caratteri, ma sarà necessario eseguire il cast della parte intposteriore a charcome chars()restituisce a IntStream.

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

Se si utilizza Java 8 con Eclipse Collections , è possibile utilizzare il metodo CharAdapterclass forEachcon un riferimento lambda o metodo per iterare su tutti i caratteri in a String.

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

Questo esempio particolare potrebbe anche utilizzare un riferimento al metodo.

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

Nota: sono un committer per le raccolte Eclipse.


1

Puoi anche usare una lambda in questo caso.

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

-7

Per Travers una stringa puoi anche usare charAt()con la stringa.

piace :

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() è il metodo di gestione delle stringhe in Java che aiuta a attraversare la stringa per caratteri specifici.


2
sai cos'è for (char st: "xyz".toCharArray()) {}?
AmitG

Questo non verrà compilato.
Maroun,

-1 off-topic (topic: for-each) e usa charAt invece di charAT
peenut
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.