2015-09-09 2 views
8

A volte voglio fare qualcosa di semplice con ogni carattere in una stringa. Sfortunatamente, poiché una stringa è immutabile, non esiste un buon modo per farlo, tranne il ciclo attraverso la stringa che può essere abbastanza dettagliato. Se invece dovessi utilizzare uno Stream, potrebbe essere molto più breve, in una o due righe.Convertire una stringa in un java.util.Stream <Character>

C'è un modo per convertire un String in un Stream<Character>?

risposta

7

È possibile utilizzare chars() metodo previsto nel CharSequence e dal String classe implementa questa interfaccia è possibile accedervi. Il metodo restituisce un chars()IntStream, quindi è necessario gettarlo ai (char) se si desidera convertire IntStream a Stream<Character>

Ad es

public class Foo { 

    public static void main(String[] args) { 
     String x = "new"; 

     Stream<Character> characters = x.chars().mapToObj(i -> (char) i); 
     characters.forEach(System.out::println); 
    } 
} 
+0

Si noti che questa soluzione non funziona se la stringa contiene caratteri Unicode che non si adattano a un carattere Java. Questo è il caso, ad esempio, di alcune lingue arcane e di emoticon. Vedi [Risposta di Tagir] (https://stackoverflow.com/a/32472793/452775) per una soluzione che gestisca ciò. – Lii

1

È possibile utilizzare il metodo che restituisce charsIntStream e mappando a char avrete Stream<Character>. mapToObj rendimenti Object valutati Stream nel nostro caso Stream di Character, perché ci hanno mappato il int per char e Java Auto Boxed a Characterinternamente.

Stream<Character> stream = "abc".chars().mapToObj(c -> (char)c); 

Inoltre, con l'aiuto di guava (com.google.common.collect.Lists) è possibile utilizzarlo come questo, che restituiscono l'elenco immutabile Character dal String.

Stream<Character> stream = Lists.charactersOf("abc").stream(); 
5

Di solito è più sicuro da usare flusso di punti di codice che è IntStream:

IntStream codePoints = string.codePoints(); 

In questo modo Unicode coppie di surrogati saranno fuse in un'unica codepoint, in modo da avere risultati corretti con tutti i simboli Unicode . Esempio di utilizzo:

String result = string.codePoints().map(Character::toUpperCase) 
     .collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append) 
     .toString(); 

Si noti inoltre che si evita la boxe, quindi potrebbe essere ancora più efficace di elaborazione Stream<Character>.

Un altro modo per raccogliere tale flusso è quello di utilizzare separata StringBuilder:

StringBuilder sb = new StringBuilder(); 
String result = string.codePoints().map(Character::toUpperCase) 
         .forEachOrdered(sb::appendCodePoint); 

Mentre tale approccio sembra meno funzionale, può essere più efficace se si dispone già di un StringBuilder o desidera concatenare qualcosa di più in seguito alla stessa stringa.

+1

Più uno per suggerire codePoint() in preferenza a chars(). –