# Array mit Schleife durchlaufen - guter Stil?



## gast (2. Apr 2007)

Hallo zusammen,

mich würde interessieren, welche Variante stilvoller und/oder perfomanter ist:


```
...
ArrayList<String> list = new ArrayList<String>();

//ArrayList wird gefüllt
...

//Variante 1:
for (int i = 0; i < list.size(); i++) {
   String x = list.get(i);
   ...
}

//Variante 2:
String x;
for (int i = 0; i < list.size(); i++) {
   x = list.get(i);
   ...
}
```

Also innerhalb jedes Mal neu deklarieren oder einmal ausserhalb?
Dachte mir, wenn ichs innerhalb deklariere, wird die Variable jedesmal verworfen und vom Garbage Collector eingesammelt. Wenn ichs ausserhalb deklariere, wird bei jeder neuen Zuweisung der alte Wert verworfen, also GC.
Sind als beide Varianten gleich performant?

Danke schon mal und Grüße.


----------



## Marco13 (2. Apr 2007)

Man weiß nicht, was der Compiler da für einen Bytecode draus macht, und noch weniger, was der Just-In-Time-Compiler dann daran noch optimiert. FALLS (!) es überhaupt einen Geschwindigkeitsunterschied gibt (was ich nicht glaube) ist der vernachlässigbar gering. Bei String ist das sogar nochmal was anderes, weil die intern nochmal in einem Pool liegen. Aber auch bei anderen Objekten dürfte es in bezug auf die Geschwindigkeit egal sein.

Das heißt, man sollte die "Schönere" Variante verwenden. Und da man (imho, bis auf seltenSTe Ausnahmen) den Gültigkeitsbereich von Variablen immer so klein wie möglich halten sollte, wäre das Variante 1.


----------



## Wildcard (2. Apr 2007)

Der Compiler/HotSpot-Compiler bügelt dir solche Sachen in der Regel aus, das ist also eigentlich egal.
Dein Stil ist allerdings nicht so optimal.
1. Verwende ein Interface aus der Collection API als Variablentyp
2. Nimm eine foreach Schleife oder einen Iterator


----------



## Gast (2. Apr 2007)

Wieso Collection statt Array?

Wieso foreach-Schleife? Ich muss den Index auslesen und in einem global(er)en int speichern, wenn eine bestimmte Bedingung erfüllt ist. Mit foreach geht das nicht...


----------



## KSG9|sebastian (2. Apr 2007)

Wir haben in der Firma mal etwas in die tiefen des Hotspotcompilers geschaut.
Mit Java 1.4 ist folgende Variante am schnellsten:


```
List aList = new ArrayList();

for(int i=0,j=aList.size(); i<j; i++){
 doSomething(aList.get(i));
}
```

bei 1.5 würde ich die foreach-Schleife empfehlen


```
List<String> aList = new ArrayList<String>();

for(String s : aList){
 doSomething(s);
}
```


----------



## Wildcard (2. Apr 2007)

Gast hat gesagt.:
			
		

> Wieso Collection statt Array?
> 
> Wieso foreach-Schleife? Ich muss den Index auslesen und in einem global(er)en int speichern, wenn eine bestimmte Bedingung erfüllt ist. Mit foreach geht das nicht...


Wenn du ein's der Interfaces verwendest hast du gleiche Funktionalität, bist aber flexibler weil du nicht auf eine Implemenierung festgelegt.
Die Index Sache funktioniert beispielsweise bei der ArrayList noch, hast du aber eine LinkedList fliegst du auf die Performance Nase.
Daher immer besser die foreach Schleife oder einen Iterator und einen Index mitlaufen lassen wenn man ihn denn braucht(zumindest wenn man eine Liste nicht nur lokal verwendet).

@KSG9|sebastian
Die Unterschiede halte ich für verschwindent gering, Da lohnt es kaum sich Gedanken zu machen.


----------



## KSG9|sebastian (3. Apr 2007)

natürlich ist der Unterschied verschwindent gering, aber je nach Größe der Anwendung macht es schon Sinn darüber nachzudenken.
Und bei der Größe unserer Anwendung macht das teilweise einen markanten Unterschied


----------



## SlaterB (3. Apr 2007)

Marco13 hat gesagt.:
			
		

> FALLS (!) es überhaupt einen Geschwindigkeitsunterschied gibt (was ich nicht glaube) ist der vernachlässigbar gering. Bei String ist das sogar nochmal was anderes, weil die intern nochmal in einem Pool liegen.


hier werden nur Objektreferenzen aus einer vorhandenen Liste geholt (nicht erzeugt),
da dürfte es keinen Unterschied zwischen Strings und anderen Objekten geben?


----------



## Ark (3. Apr 2007)

Ich glaube, es gibt zwischen der traditionellen for-Schleife und foreach bei Arrays(!) keinen Unterschied. Ich denke auch, dass es hier ebenfalls keinen(!) Unterschied gibt:


```
for(int i=0;i<a.length;i++){
   Klasse x=a[i];
   x.doSomething();
}

// vs.

Klasse x;
for(int i=0;i<a.length;i++){
   x=a[i];
   x.doSomething();
}
```

Grund: AFAIR sind die Deklarationen nur für den Compiler interessant, aber nicht mehr zur Laufzeit, wenn es beide Male darum gehe, Speicherplatz zu reservieren.


```
while(true){
   int a=1;
}
```
Im Gegensatz zu anderen Sprachen wird der Speicher hier nicht voll. 

Oder habe ich jetzt etwas übersehen/falsch verstanden?

ArK


----------



## SlaterB (3. Apr 2007)

voll muss es nicht werden, es geht um die Zeit, den Speicherplatz zu organisieren (anfordern, verfügen, freigeben),

zumindest beim Aufruf einer Suboperation wird ja eine Menge getan..


----------



## KSG9|sebastian (3. Apr 2007)

@Ark: Bei 1.4 gibt es DEFINITIV einen Unterschied. Da verwette ich mein Auto drauf. Es ist deshalb schneller weil der Hotspotcompiler sonst bei jedem Schleifendurchlauf size() auf die Collection ausführt. Und als lokale Variable wird es nur einmal aufgerufen. Und das macht einen minimalen Unterschied. Zumindest bei 1.4..

Denk mit 1.5 wurde das geändert. Da wir kein 1.5 benutzen hab ich kein Plan ob es da noch passt.


----------



## SlaterB (3. Apr 2007)

@KSG9|sebastian
das mit size ist klar, darüber diskutiert keiner,
die ursprüngliche Frage war ja die lokale Variable


----------



## Der Müde Joe (3. Apr 2007)

@SlaterB + KSG9:

dann macht doch ne High Speed schleife


```
for( int i = 0, size = collection.size() ; i<size ; i++)
```

schon ist das size() wegoptimiert...

 :bae:


----------



## SlaterB (3. Apr 2007)

das ist doch das was KSG9|sebastian schon geschrieben hatte 
(wenn auch mit Tippfehler)


----------



## KSG9|sebastian (3. Apr 2007)

hab ich doch geschrieben, Tippfehler berenigt


----------



## Der Müde Joe (3. Apr 2007)

mein Fehler..überlesen in Rausch der Geschwindigkeit


----------



## Gast (3. Apr 2007)

Aehm wow, danke für die vielen Antworten.

Aber: mit der for each Schleife kann ich doch immernoch nicht auf den Index zugreifen. oder?

```
int index = -1;
for (int i = 0, int size = collection.size(); i < size; i++) {
   if (bedingung) index = i;
}
```
Somit finde ich den letzten Index, der meine Bedingung erfüllt. Ist es da wirklich besser eine for each Schleife zu verwenden und einen Zähler extra mitlaufen zu lassen?
Der Vorteil von foreach ist, dass eine LinkedList nicht mit index sondern mit nextElement() durchlaufen wird, habe ich das richtig verstanden?

Ich bin auch noch nicht 100% von dieser Collectione-Sache überzeugt, da ich ziemlich sicher nur ArrayLists verwende(n werde).

Gruß.


----------



## KSG9|sebastian (3. Apr 2007)

eine ArrayList IST eine Collection

Der Vorteil wenn du z.B. nur ein Listinterface zurückgibst ist der, dass du die Implementierung darunter frei austauschen kannst.
Wenn du z.B. einfällt dass du statt ner ArrayList eine LinkedList brauchst kannst das einfach austauschen. Also so z.B.


```
public class MeinModel{
   private List<String> irgendwas = new LinkedList<String>();

   public List<String> getIrgendwas(){
      return irgendwas;
   }
}

public class Blah{
   private MeinModel model;
   public irgendwo(){
      for(String s : model.getIrgendwas()){
         tuWasMit(s);
      }
   }
}

// Wenn dir jetzt einfällt das die Linkedlist eigentlich fürn AA 
// ist, dann tausch's einfach aus. Am restlichen Code ändert sich
//nichts

//ausgetauscht:
public class MeinModel{
   private List<String> irgendwas = new ArrayList<String>();

   public List<String> getIrgendwas(){
      return irgendwas;
   }
}
```

Der restliche Code bleibt gleich.
Wenn du den Index willst (wozu auch immer):


```
int index = 0;
for(String s : model.getIrgendwas()){
  tuWasMit(s);
  tuWasMitIndex(index);
  index++;
}
```


----------



## Marcel_Handball (3. Apr 2007)

zu dem Unterschied der foreach Schreife und der normalen for -Schleife:



> Intern setzt der Compiler diese erweiterte foreach-Schleife ganz klassisch um, sodass *der Bytecode unter beiden Varianten gleich ist*. Nachteile der foreach Variante sind jedoch:
> 
> * Das erweiterte for läuft immer das ganze Feld ab. Anfang- und Ende-Index lassen sich nicht ausdrücklich setzen.
> 
> ...



www.galileocomputing.de/openbook/javainsel6/javainsel_03_009.htm#mjcdaa123ec655f6dfe574bd9db37a7ba7 :3.9.9 Die erweiterte for-Schleife


----------



## Leroy42 (3. Apr 2007)

Ark hat gesagt.:
			
		

> ```
> while(true){
> int a=1;
> }
> ...



Welche anderen Sprachen meinst du?  :shock: 

Bei allen Sprachen, die Block-lokale Variablen kennen, wird der
Speicher durch die Anweisungen doch nicht voll.

Die Abarbeitung dieser Anweisung zieht sich eben nur ein Wenig hin.


----------



## Gast (3. Apr 2007)

Also nochmal danke für alles, top Forum hier!


----------

