Как применить цикл for-each к каждому символу в строке?

189

Поэтому я хочу повторить для каждого символа в строке.

Вот я и подумал:

for (char c : "xyz")

но я получаю ошибку компилятора:

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

Как я могу это сделать?

Линдон Уайт
источник

Ответы:

333

Самый простой способ для каждого каждого charв это Stringиспользовать toCharArray():

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

Это дает вам краткость для каждой конструкции, но, к сожалению String(которая является неизменной), необходимо выполнить защитную копию, чтобы сгенерировать char[](которая является изменяемой), так что есть некоторый штраф стоимости.

Из документации :

[ toCharArray()возвращает] вновь выделенный символьный массив , длина которого равна длине этой строки и содержимое которого инициализируется, чтобы содержать последовательность символов, представленную этой строкой.

Существуют более подробные способы итерации по символам в массиве (обычные для цикла и CharacterIteratorт. Д.), Но если вы готовы платить toCharArray()за каждый, это самый лаконичный вариант.

polygenelubricants
источник
1
Признает ли компилятор, что точная копия не нужна, и применит соответствующие оптимизации?
Pacerier
1
@Pacerier Нет, текущие компиляторы Java никогда не будут оптимизировать код.
RAnders00
1
@ RAnders00 Так в таком случае toCharArray( )вызывается 3 раза?
denvercoder9
1
При длине строки 211900000время завершения for (char c : str.toCharArray()) { }~ 250 мс, а время завершения for (char c : charArray) { }<10 мс. Конечно, эти значения времени будут зависеть от аппаратного обеспечения, но вывод заключается в том, что один метод значительно дороже, чем другой.
denvercoder9
7
@RafiduzzamanSonnet: Нет, toCharArray()это не внутри тела цикла; он вызывается только один раз, а затем цикл повторяется по полученному массиву. (Цикл for-each отличается от общего for-loop, который оценивает условие остановки каждую итерацию.)
not-just-yeti
50
String s = "xyz";
for(int i = 0; i < s.length(); i++)
{
   char c = s.charAt(i);
}

 

Мэтью Флэшен
источник
7
ОП ожидает улучшенного цикла.
AmitG
3
Вниз проголосовали, потому что это не совсем то, о чем просил ОП. Хотя это правильное решение, оно совсем не то, о чем просят
Сирены,
1
Независимо от того, что ожидал OP, он имеет лучшую производительность, чем для каждого, я думаю.
Эрик Ван
9

Другое полезное решение, вы можете работать с этой строкой как массивом String

for (String s : "xyz".split("")) {
    System.out.println(s);
}
kyxap
источник
Элегантно, но, к сожалению, он не работает, если какие-либо элементы строки split()отображаются более чем на один символ Java, что имеет место почти для всех смайликов. Например, этот вариант вашего примера будет зацикливаться четыре раза, а не три:for (String s : "x😁z".split("")) { System.out.println(s); }
skomisa
5

Вам необходимо преобразовать объект String в массив char, используя метод toCharArray() класса 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
источник
4

В Java 8 мы можем решить это как:

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

Метод chars () возвращает, IntStreamкак указано в документе :

Возвращает поток значений int, расширяющих ноль, из этой последовательности. Любой символ, который отображается на суррогатную кодовую точку, пропускается через интерпретацию. Если последовательность видоизменяется во время чтения потока, результат не определен.

Почему использовать, forEachOrderedа не forEach?

Поведение forEachявляется явно недетерминированным, когда as forEachOrderedвыполняет действие для каждого элемента этого потока в порядке обнаружения потока, если поток имеет определенный порядок встречи. Так forEachчто не гарантирует, что заказ будет сохранен. Также проверьте этот вопрос для получения дополнительной информации.

Мы также можем использовать codePoints()для печати, см. Этот ответ для более подробной информации.

akhil_mittal
источник
Это создает несколько объектов, поэтому этот ответ не будет полным без предупреждения о том, что это может быть менее эффективным, чем простой индексированный цикл.
инструментальный инструмент
4

К сожалению, Java не делает Stringреализацию Iterable<Character>. Это можно легко сделать. Есть, StringCharacterIteratorно это даже не реализуется Iterator... Так что сделайте свой собственный:

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

Теперь вы можете (несколько) легко запустить for (char c : new CharSequenceCharacterIterable("xyz"))...

Ossifer
источник
3

Если вы используете Java 8, вы можете использовать chars()a Stringдля получения Streamсимволов, но вам нужно будет привести intобратно к a, charкак chars()возвращает IntStream.

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

Если вы используете Java 8 с коллекциями Eclipse , вы можете использовать метод CharAdapterкласса forEachс лямбда-ссылкой или ссылкой на метод для перебора всех символов в String.

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

Этот конкретный пример может также использовать ссылку на метод.

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

Примечание: я являюсь коммиттером для Eclipse Collections.

Дональд Рааб
источник
1

Вы также можете использовать лямбду в этом случае.

    String s = "xyz";
    IntStream.range(0, s.length()).forEach(i -> {
        char c = s.charAt(i);
    });
ander4y748
источник
-7

Для Travers a String вы также можете использовать charAt()эту строку.

лайк :

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() это метод обработки строк в Java, который помогает пройти строку для конкретного символа.

user1690439
источник
2
ты знаешь что for (char st: "xyz".toCharArray()) {}такое?
AmitG
Это не скомпилируется.
Maroun
-1 не по теме (тема: для каждого) и используйте charAt вместо charAT
peenut