For-each döngüsünü bir String'deki her karaktere nasıl uygularım?


189

Bu yüzden bir karakter dizisindeki her karakter için yineleme yapmak istiyorum.

Ben de düşündüm ki:

for (char c : "xyz")

ama bir derleyici hatası alıyorum:

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

Bunu nasıl yapabilirim?

Yanıtlar:


333

İçin-her her en kolay yolu charbir de Stringkullanmaktır toCharArray():

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

Bu size her bir yapının özlü olmasını sağlar, ancak maalesef String(değişmez), char[](değişebilir) oluşturmak için savunma kopyası yapmalıdır , bu yüzden bazı maliyet cezaları vardır.

Gönderen belgeler :

uzunluğu bu dizenin uzunluğu olan ve içeriği bu dizeyle temsil edilen karakter dizisini içerecek şekilde başlatılan yeni atanmış bir karakter dizisini [ toCharArray()döndürür] .

Bir dizideki karakterler (döngü için düzenli CharacterIterator, vb.) Üzerinde yineleme yapmanın daha ayrıntılı yolları vardır, ancak toCharArray()her birinin maliyetini ödemeye istekli iseniz -en özlüdür.


1
Derleyici, gerçek bir kopyanın gerekli olmadığını fark edecek ve uygun optimizasyonları uygulayacak mı?
Pacerier

1
@Pacerier Hayır, mevcut Java derleyicileri hiçbir zaman kodu optimize etmez.
RAnders00

1
@ RAnders00 Peki, bu durumda toCharArray( )3 kez denir?
denvercoder9

1
Dize uzunluğu ile 211900000, tamamlanması for (char c : str.toCharArray()) { }için geçen süre ~ 250 ms'dir ve tamamlanması for (char c : charArray) { }için geçen süre <10 ms'dir. Tabii ki, bu zaman değerleri donanıma bağlı olacaktır, ancak paket servisi olan şey bir yöntemin diğerinden önemli ölçüde maliyetli olmasıdır.
denvercoder9

7
@RafiduzzamanSonnet: Hayır, toCharArray()döngü gövdesinin içinde değil; yalnızca bir kez çağrılır ve daha sonra döngü bu sonuç dizisi üzerinde yinelenir. (For-each döngüsü, forher yinelemenin durma koşulunu değerlendiren general -loop'tan farklıdır .)
sadece-yeti değil

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

 


7
OP döngü için geliştirilmiş.
AmitG

3
Down oy kullandı çünkü OP'nin istediği bu değildi. Bu geçerli bir çözüm olmakla birlikte, tamamen sorulan şey değildir
Sirens

1
OP'nin beklentisi ne olursa olsun, bunun her biri için olduğundan daha iyi bir performansı var.
Eric Wang

9

Başka bir yararlı çözüm, bu dize ile Dize dizisi olarak çalışabilirsiniz

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

Zarif, ancak maalesef dizenin herhangi bir öğesinin split()birden fazla Java karakteriyle eşleşmesi işe yaramazsa , bu neredeyse tüm ifadeler için geçerlidir. Örneğin, örneğinizin bu varyasyonu üç yerine dört kez for (String s : "x😁z".split("")) { System.out.println(s); }
dönecektir

5

toCharArrayString sınıfının () yöntemini kullanarak String nesnesini char dizisine dönüştürmeniz gerekir :

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 bunu olarak çözebilir:

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

Yöntem karakter () bir döner IntStreambelirtildiği gibi doküman :

Bu diziden char değerlerini sıfır genişleten bir int akışı döndürür. Bir vekil kod noktasına eşlenen tüm karakterler yorumlanmadan geçirilir. Akış okunurken dizi mutasyona uğratılırsa, sonuç tanımsız olur.

Neden kullanmalı forEachOrderedve kullanmıyorsunuz forEach?

Öğesinin davranışı forEachaçıkça belirsizdir; burada forEachOrderedakış, tanımlı bir karşılaşma sırasına sahipse akışın karşılaşma sırasında bu akışın her öğesi için bir eylem gerçekleştirir . Bu yüzden forEachsiparişin korunacağını garanti etmez. Ayrıca daha fazla bilgi için bu soruyu kontrol edin .

codePoints()Yazdırmak için de kullanabiliriz , daha fazla ayrıntı için bu cevaba bakın.


Bu, birden çok nesne oluşturur, bu nedenle, bu basit bir dizinli döngüden daha az verimli olabileceği uyarısı olmadan tam değildir.
toolforger

4

Maalesef Java yapmaz Stringuygulamak Iterable<Character>. Bu kolayca yapılabilir. Var StringCharacterIteratorama uygulanmıyor bile Iterator... Öyleyse kendin yap:

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

Artık (biraz) kolayca koşabilirsiniz for (char c : new CharSequenceCharacterIterable("xyz"))...


3

Java 8 kullanıyorsanız chars(), karakterleri Stringalmak için a tuşunu kullanabilirsiniz Stream, ancak intgeri dönüşünü a charolarak chars()döndürmeniz gerekir IntStream.

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

Eclipse Collections ile Java 8 kullanıyorsanız, a. İçindeki tüm karakterleri yinelemek için CharAdaptersınıf forEachyöntemini lambda veya yöntem başvurusuyla kullanabilirsiniz String.

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

Bu özel örnek bir yöntem başvurusu da kullanabilir.

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

Not: Eclipse Collections için bir komisyoncuyum.


1

Bu durumda bir lambda da kullanabilirsiniz.

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

-7

Bir Dizeyi Travers için dize charAt()ile de kullanabilirsiniz .

sevmek :

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 karakter dizisi işleme özel karakter için dize Travers yardımcı yöntemidir.


2
ne biliyor musunuz for (char st: "xyz".toCharArray()) {}nedir?
AmitG

Bu derlenmeyecektir.
Maroun

-1 konu dışı (konu: her biri için) ve charAT yerine charAt kullanın
peenut
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.