2015-09-09 2 views
8

Иногда я хочу сделать что-то простое с каждым символом в строке. К сожалению, поскольку строка неизменна, нет никакого хорошего способа сделать это, кроме цикла через строку, которая может быть довольно многословной. Если бы вы использовали Stream вместо этого, это могло бы быть сделано намного короче, всего лишь в строке или двух.Преобразование строки в java.util.Stream <Character>

Есть ли способ конвертировать String в Stream<Character>?

ответ

7

Вы можете использовать chars() метод, предусмотренный в CharSequence и так String класс реализует этот интерфейс, вы можете получить доступ к нему. Метод chars() возвращает IntStream, так что вам нужно, чтобы привести его к (char), если вы хотели бы конвертировать IntStream в Stream<Character>

Э.Г.

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

Обратите внимание, что это решение не работает, если строка содержит символ Юникода, который не вписывается в Java-символ. Так обстоит дело, например, с некоторыми тайными языками, а также с смайликами. См. Ответ [Тагир] (https://stackoverflow.com/a/32472793/452775) для решений, которые обрабатывают это. – Lii

1

Вы можете использовать chars метод, который возвращает IntStream и отображение его char вы будете иметь Stream<Character>. mapToObj возвращает Object значных Stream в нашем случае Stream из Character, потому что мы сопоставили int в char и Java Auto штучной это Characterвнутренне.

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

Кроме того, с помощью гуавы (com.google.common.collect.Lists), вы можете использовать его, как это, возвращающие неизменный список Character из String.

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

Это, как правило, более безопасно использовать поток кодовых точек, который является IntStream:

IntStream codePoints = string.codePoints(); 

Таким образом, Unicode пары суррогатных будут объединены в один элемент кода, так что вы будете иметь правильные результаты с любыми символами Unicode , Пример использования:

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

Также обратите внимание, что вам избежать бокс, таким образом, это может быть даже более эффективным, чем обработка Stream<Character>.

Другой способ сбора такой поток должен использовать отдельный StringBuilder:

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

Хотя такой подход выглядит менее функциональным, он может быть более эффективным, если у вас уже есть StringBuilder или хотите объединить что-то более позднее к ту же строку.

+1

Плюс один для подсказки codePoints() вместо chars(). –

Смежные вопросы