2016-08-10 4 views
0

stieß ich auf Code wie unten mehrmals gesagt:Ist es eine gute Praxis String.toCharArray() in for-Schleife

for (char c : s.toCharArray()) { 
    .... 
} 

ich mich, wenn s.toCharArray() nur einmal oder s.length mal excuted excuted? Und was ist mit dem Fall unten?

for (int i = 0; i < s.toCharArray().length; i++) { 
    .... 
} 

durch Kommentare inspiriert, haben einige Test:

Fall 1: Ausfürung Zeit: 692,664

String s = "dfsdfjglsdlghsl"; 
    for(int i = 0 ; i < 25; i++){ 
     s += s; 
    } 
    long start_time = System.nanoTime(); 

    for(char c : s.toCharArray()){ 
     int i = 0; 
    } 

    long end_time = System.nanoTime(); 
    double excution_time = (end_time - start_time)/1e6; 
    System.out.println(excution_time); 

Fall 2: Ausfürung Zeit: 688,217

String s = "dfsdfjglsdlghsl"; 
    for(int i = 0 ; i < 25; i++){ 
     s += s; 
    } 
    long start_time = System.nanoTime(); 

    char[] carrays = s.toCharArray(); 
    for(char c : carrays){ 
     int i = 0; 
    } 

    long end_time = System.nanoTime(); 
    double excution_time = (end_time - start_time)/1e6; 
    System.out.println(excution_time); 

Fast das gleiche. So sollte s.toCharArray() im ersten Fall nur einmal ausgeführt werden.

+5

Es wird nur einmal ausgeführt. Sie finden das entsprechende Basis-for-Schleife für die erweiterte for-Schleife [in JLS] (https://docs.oracle.com/javase/specs/jls/se8/html/jls-14.html#jls-14.14.2) (Suche nach "Andernfalls hat der Ausdruck notwendigerweise einen Array-Typ, T []."). –

+0

In Ihrem zweiten Beispiel wird 's.toCharArray(). Length' bei jeder Ausführung der Schleife aufgerufen. Das ist bedauerlich, weil es die Zeichenfolge jedes Mal in ein neues Array kopiert, was diese for-Schleife in der String-Länge mindestens quadratisch macht. Es entspricht auch dem konstanten Zeitausdruck 's.length()'; Ich würde das letztere empfehlen. –

+0

+1 für Any's Kommentar, von dem ich denke, dass er in eine Antwort umgewandelt werden kann. Mein Kommentar ist: führe dies im Debugger aus und setze einen Haltepunkt, um Andys Behauptungen zu beobachten. –

Antwort

2

Nach JLS Sec 14.14.2, eine verbesserte für Aussage über eine Array-Typ:

L1: L2: ... Lm: 
for ({VariableModifier} TargetType Identifier : Expression) { 
    Statement 
} 

entspricht der folgenden Grund für Aussage:

T[] #a = Expression; 
L1: L2: ... Lm: 
for (int #i = 0; #i < #a.length; #i++) { 
    {VariableModifier} TargetType Identifier = #a[#i]; 
    Statement 
} 

So:

for (char c : s.toCharArray()) { 
    // ... 
} 

ist entspricht:

T[] cs = s.toCharArray(); 
for (int i = 0; i < cs.length; i++) { 
    char c = cs[i]; 
    // ... 
} 

So wird die s.toCharArray() nur einmal ausgeführt.

jedoch in

for (int i = 0; i < s.toCharArray().length; i++) { 

die s.toCharArray() wird vor jeder Wiederholung der Schleife ausgeführt. Dies ist nicht wünschenswert, da es ein neues Array der Länge s.length() erstellt, die Zeichen in dieses Array kopiert, dann die Länge des Arrays übernimmt und die Daten verwirft.

Da die Schleife s.length() mal ausgeführt wird, ist diese Schleife dann mindestens quadratisch in der Stringlänge.

Es ist viel rechen billiger zu verwenden:

for (int i = 0; i < s.length(); i++) { 

, die linear in der String-Länge ist.

Verwandte Themen