Variable Initialisieren, aber wo?

Semptic

Mitglied
Kurze und blöde Frage:

Welche folgender Verwendungen ist sinvoller und warum?
1:
Java:
for (Iterator<Person> i = personen.iterator(); i.hasNext();) {
     Person p = i.next();
     p.tuwas();
     p.tunochwas();
}
2:
Java:
Person p;
for (Iterator<Person> i = personen.iterator(); i.hasNext();) {
     p = i.next();
     p.tuwas();
     p.tunochwas();
}
 
Ich wäre für
Java:
	for (Person person : personen) {
	    person.tuwas();
	    person.tunochwas();
	}

Wenn du allerdings z.B. eine spezielle Person suchst und diese auch außerhalb des Schleifen-Blockes benutzt werden soll, kommst du wohl nicht drumherum vorher eine Variable zu deklarieren (und wahrscheinlich mit null zu initialisieren)
 
Nennt sich ForEach und stellt in Bytecode nahezu das Gleiche dar wie deine erste Variante. Ist halt hübscher und weniger Schreibarbeit aber nicht immer zu gebrauchen und erst seit Java (ähm) 1.5 dabei,
 
Wenn Du nur Listen traversierst, fährst Du mit dem HighSpeed-Idiom nach Bloch am besten :

Java:
for (int i = 0, n = personen.size(); i < n; i ++) {
     Person p = personen.get(i);
     p.tuwas();
     p.tunochwas();
}
 
Wenn Du nur Listen traversierst, fährst Du mit dem HighSpeed-Idiom nach Bloch am besten :
[...]

Woher hast du das denn? Für verkette Listen ist get(index) doch recht langsam, weil jedesmal wieder die komplette Liste durchlaufen werden muss. Die foreach-Schleife ist in den meißten Fällen der beste Weg.

und den Teil mit n = personen.size() macht man ja normalerweise auch nur, wenn der Aufruf von size() recht aufwändig ist.
 
Bloch: Effektiv Java-Programmieren

Das mit den verketteten Listen stimmt schon, ist aber auch leider die einzige Liste die performanter mit foreach läuft :autsch:

Das ist auch nur so, weil hier der Iterator schneller ist. Der Compiler baut aus dem foreach nämlich eine Iteratorschleife und die ist nunmal bei normalen Listimplementierungen teurer.
 
Zuletzt bearbeitet:
Effective Java 2nd Edition hab ich auch hier neben mir liegen, aber irgendwie finde ich den Namen "High-Speed-Idiom" hier nicht. Item 45 "Minimize the scope of local variables" sagt dass man die obere Grenze schon vorab berechnen soll wenn die Methode jedesmal das selbe Ergebnis liefern würde und Item 46 "Prefer for-each loops to traditional for loops" sagt, dass die foreach-Schleife keinen Performancenachteil hat und man sie (wenn möglich) immer der for-Schleife vorziehen sollte.
 
Bei der ArrayList ist dann foreach schneller oder das umständliche mit dem iterator?

€dit: Frage wurde beantwortet bevor ich sie stellen konnte.
 
Zuletzt bearbeitet:
@Andiv Ich habe hier auf Arbeit leider nur die englische Version. Schlag mal Seite 143 auf, "High-performance idom for iterating over random access lists" ... Ich möchte meinen, in der deutschen Übersetzung wird es High - speed genannt, aber das kann auch ein Erinnerungsproblem sein 😉 Der Name soll auch egal sein, denn es geht um die Programmierung der Schleife. 🙂

Effective Java: programming language ... - Google Bücher

Den Performancenachteil kannst Du selbst messen, bzw. anhand des Bytecodes prüfen 😉
 
Zuletzt bearbeitet:
Da stellt sich für mich die Frage was heißt Random Acces?
Die Übersetzung ist klar aber nicht was es Programmiertechnisch heißt. Denn ein Zufälliger Zugriff ist für mich nicht die Liste von 0 bis ende durchzugehen sondern auf Element x zuzugreifen.
 
Listen mit wahlfreiem Zugriff - die bist also nicht gezwungen, eine Liste in einer gewissen, zumeist vorbestimmten Reihenfolge abzuarbeiten.

Ein Gegenbeispiel wäre ein Stack: Um an das dritte Element zu kommen, musst du erst die beiden vorherigen Elemente vom Stack nehmen, während du bei der Liste direkt auf das dritte Element zugreifen kannst, ohne zuvor auf die Elemente 1 und 2 zugreifen zu müssen.
 
@fastjack
Ich hab jetzt mein Exemplar gerade nicht bei mir, aber ich glaube du sprichst von der 1. Ausgabe. Zumindest dein Link verweist auf die 1. Ausgabe. Ich meine die Sätze mit dem High-Speed hat Joshua Block nicht in die 2. Ausgabe übernommen, eben weil die foreach-Schleife keinen Performancenachteil gegenüber der klassischen for-Schleife hat.
 
@andiv

eben weil die foreach-Schleife keinen Performancenachteil gegenüber der klassischen for-Schleife hat

Das ist leider nicht ganz korrekt. Probiers einfach selbst mal für eine ArrayList aus 😉 Aus dem Bytecode wirst Du erkennen, das der Compiler aus dem foreach immer ein Iterator-Konstrukt erzeugt. Aus der High-Speed-Schleife aber nicht, das ist der Clou. Der Iterator ist zumindest in allen Fällen, in denen die Liste auf einer Array-Repräsentation beruht, langsamer 🙂 Wie gesagt, ich spreche hier nur für die Fälle, in denen einfach nur traversiert wird. Bei der LinkedList hast Du vollkommen recht.
 
Okay, das glaube ich dir. Ich wundere mich dann trotzdem warum Joshua Bloch diese Bemerkung in der zweiten Ausgabe herausgenommen hat und schreibt, dass man die foreach-Schleife ohne Performanceverlust verwenden kann. Wahrscheinlich weil der Performancevorteil durch das High-Speed-Idiom in fast allen Fällen vernachlässigbar klein ist oder zumindest nicht den eigentlichen Flaschenhals darstellt.

Optimize?
1. Don't do it.
2. (for experts only) Don't do it yet.
 
Warum er das schreibt? K.A. Aber es schreiben immer wieder mal Leute irgendetwas um einen Hype zu fördern, der keiner ist :bae: Da ist oder war man auch bei SUN nicht sicher.
Bei größeren Listen liegt der Performanceverlust durchaus im spürbaren Bereich. Auch an kritischen Stellen, die immer wieder mal öfters durchwandert werden müssen.
 
Also in Bloch 2nd Edition steht sogar explizit:

Item 46: Prefer for-each loops to traditional for loops (Page. 212)
Note that there is no performance penalty for using the for-each loop, even for arrays. In fact, it may offer a slight performance advantage over an ordinary for loop in some circumstances, as it computes the limit of the array index only once. While you can do this by hand (Item 45), programmers don't always do so.

Ich weiß, dass man nicht immer alles direkt so glauben soll, aber Bloch hat nun mal extrem Ahnung von Java...
 
Bei größeren Listen liegt der Performanceverlust durchaus im spürbaren Bereich. Auch an kritischen Stellen, die immer wieder mal öfters durchwandert werden müssen.

wenn man wirklich so große Listen so oft durchläuft, ist es fast schon schlauer, die Daten in eine LinkedList zu kopieren,
dann ist man mit einem Iterator, etwa dem for-each-Konstrukt, wiederum schneller,

oder als Zwischenlösung direkt mit einem Array arbeiten
 
oder als Zwischenlösung direkt mit einem Array arbeiten
@SlaterB worauf basiert denn die ArrayList ?

Eigentlich benötigt man nicht mal große Listen. Es reichen schon Stellen aus, die mehrere Male angesprochen werden, z.B. Servermethoden und Ähnliches, oder halt zentrale Stellen. Selbst ein kleiner Performanceverlust kann sich dort ganz schnell summieren, oder nicht ?
Und warum soll man das foreach überall nutzen, wenn es nicht überall performant läuft? Es gibt dazu viele Diskussionen, u.a. auf StackOverflow. Es ist auch belegt, das der Iterator nicht auf jeder Datenstruktur performanter läuft als die Schleife, das sollte auch klar sein.
Ich denke es kommt sehr genau auf den Fall an, wo man foreach nutzen sollte und wo nicht. Aber generell zu behaupten, alles sollte mit foreach behandelt werden, halte ich für sehr gewagt. Blochs 2nd Edition in Ehren, aber foreach ist leider nicht das Allheilmittel 😉
 
> @SlaterB worauf basiert denn die ArrayList ?

ja und worauf basiert der Iterator?

wenn dir der zuviel Overhead ist, dann ist meine Aussage dass die Liste selber auch zuviel Overhead ist, wenn dann mit Array arbeiten
(und dann natürlich auch eine for i-Schleife, nicht Iterator über Array 😉 )

foreach ist fast genau so ein Allheilmittel wie Strings für Text,
dass man in Extremsituationen lieber mit char[] spart ist eher ein Nebenpunkt

viel spannender finde ich dagegen den fehlenden Index bei foreach, wenn man i braucht kommt man an einer for-Schleife kaum vorbei
 
@SlaterB worauf basiert denn die ArrayList ?
Arraylist macht nur ein bisschen mehr magic noch als ein 0815 Array

Ich denke es kommt sehr genau auf den Fall an, wo man foreach nutzen sollte und wo nicht. Aber generell zu behaupten, alles sollte mit foreach behandelt werden, halte ich für sehr gewagt. Blochs 2nd Edition in Ehren, aber foreach ist leider nicht das Allheilmittel 😉
und zu 99,999999% ist Performance ziemlich wurscht bzw "performantes Programmieren" eher unguenstig. Die generelle Behauptung foreach vorzuziehen ist schon richtig
 
Nachdem ich in der Regel nichts über die Implementierungsdetails der Liste wissen möchte, würde ich immer den Iterator vorziehen. Ich gehe davon aus, dass die Listenimplementierung ihren Iterator sinnvoll (=performant) implementiert hat, also z.B. bei einer indexbasierten Liste durch hochzählen des Index und bei einer sequentiellen Liste durch Navigation zum nächsten Element.
 
SlaterB hat gesagt.:
viel spannender finde ich dagegen den fehlenden Index bei foreach, wenn man i braucht kommt man an einer for-Schleife kaum vorbe

Das stimmt und ich werfe noch ein paar Kohlen ins Feuer gggg :

* Kein Zugriff auf den Iterator.
* Kein Offset möglich.
* Nicht rückwärts von hinten nach vorne laufen. Ein netter Trick, um Elemente aus der zu traversierenden Liste zu entfernen,
* Kein Überspringen von Elementen. (O.k. continue geht, aber nicht i+=4 etc.)
* Mit einem Index lassen sich nicht gleichzeitig zwei Datenstrukturen durchlaufen.
* Liste nicht modifizierbar.

@rambozola löl zurück 😉 Das hat ThreadPool bereits getan

http://www.java-forum.org/java-basics-anfaenger-themen/88698-each-loop.html

Erklär doch mal, warum es so ist :applaus:
 
Zuletzt bearbeitet:
Das ist doch wohl nicht Dein Ernst oder ?
freilich, vielleicht eine 9 hinten ist uebertrieben ;-)

lass mich vll die Aussage anders formulieren:

zu 99,99999% wird unter dem faelschlichen Vorwand von Performance ein uebler, mieser und schlechter code produziert.

wenn jemand lust hat kann er die ueblichen "performance-zitate" anbringen.

bygones

BTT
 
Das stimmt und ich werfe noch ein paar Kohlen ins Feuer gggg :

* Kein Zugriff auf den Iterator.
* Kein Offset möglich.
* Nicht rückwärts von hinten nach vorne laufen. Ein netter Trick, um Elemente aus der zu traversierenden Liste zu entfernen,
* Kein Überspringen von Elementen. (O.k. continue geht, aber nicht i+=4 etc.)
* Mit einem Index lassen sich nicht gleichzeitig zwei Datenstrukturen durchlaufen.
* Liste nicht modifizierbar.

@rambozola löl zurück 😉 Das ThreadPool bereits getan

http://www.java-forum.org/java-basics-anfaenger-themen/88698-each-loop.html

Naja. die Kohlen ins Feuer... bisher bezog sich die Diskussion ausschließlich über das Komplette iterieren einer Liste. Deine Fälle sind allesamt eher spezielle Fälle, bei denen man um eine normale for-Schleife nicht herum kommt. Insofern ist das hier nicht relevant. Ansonsten kann ich bygones und SlaterB nur zustimmen.
 
Das schreibst Du sehr schön. Ich hatte auch nur geschrieben daß man den Einsatz des foreach nicht pauschalisieren sollte und sich dessen Performanceverlust vor Augen halten sollte, mehr war eigentlich nicht gemeint.
 
Ich mache keine Witze. Mach doch einfach mal selber nen Performancetest 😉 Wenn Du Hilfe dabei brauchst, sag einfach Bescheid.

Verschiedene Listen mit verschiedenen Schleifenarten durchgehen. Zeiten messen, vergleichen.
Java 5 oder 6, Win oder Linux spielt keine Rolle. Du solltest mehr als 1 bis 10 Elemente nehmen und die Tests öfters wiederholen. Wenn Du es drauf hast, Bytecode vergleichen und festellen warum es Unterschiede gibt 🙂

P.S.: Gibt es einen besonderen Grund, weshalb der Link in Deiner Signatur nicht geht, oder ist das ein Witz? :bae:
 
Zuletzt bearbeitet:
Ich mache keine Witze. Mach doch einfach mal selber nen Performancetest 😉 Wenn Du Hilfe dabei brauchst, sag einfach Bescheid.
Au ja den Test will ich sehen, hilf mir bitte.

P.S.: Gibt es einen besonderen Grund, weshalb der Link in Deiner Signatur nicht geht, oder ist das ein Witz? :bae:
Du redest gerade mit einem Bugmenot Account, keine Ahnung wer den Link in die Signatur geschrieben hat. Immerhin ist der Account auch schon ein bisschen älter als deiner...
 
rambozola hat gesagt.:
Du redest gerade mit einem Bugmenot Account, keine Ahnung wer den Link in die Signatur geschrieben hat. Immerhin ist der Account auch schon ein bisschen älter als deiner...

Wenigstens bist Du noch Herr der Dinge ....

rambozola hat gesagt.:
... hilf mir bitte.

Hab ich mir schon fast gedacht.

Füll einfach Deine Implementierung in diesen Rahmen:

Java:
public class Test {
}
 

Zurück
Oben