# Beliebig viele Werte in Array zwischenspeichern



## The_Virus (1. Jul 2011)

Ich soll mal wieder ein Programm für die Uni schreiben. Es geht um die Berechnung von Rationalen Zahlen. In meinem Programm wird eine Rechnung ausgeführt z.B. Bruch1 + Bruch2 und das Ergebnis ausgegeben. Die Aufgabe (Bruch1 + Bruch2 = Ergebnis) soll nun in einem Array gespeichert werden. Danach wird abgefragt, ob nochmal gerechnet werden soll und das Programm läuft von vorne. Wenn man beenden will (Abfrage auf "nein") soll das Programm alle gespeicherten Aufgaben nochmal ausgeben. Doch ein Array hat eine feste Länge und ist nicht variabel. Wenn ich nun mein Array auf 5 festlege und 6 Berechnungen durchführe, gibt es ExceptionOutOfBounds.

Eine mögliche Lösung wäre eine ArrayList, denn die ist variabel. Doch in der Aufgabe steht eigentlich explizit Array nicht ArrayList. Und vielleicht gibt es ja da einen Trick, um das doch mit einem Array zu lösen ?!
Eine andere unschöne aber simple Lösung wäre, dem Array einfach 1000 Stellen zu geben und dann am Ende alle null Stellen irgendwie "abzuschneiden" bzw. sie einfach nicht auszugeben.

Hier mal die main() zu meinem Prog. Hab es jetzt erstmal mit ArrayList gelöst.

```
package paketRationaleZahlen;
import java.util.ArrayList;

public class Start {

	public static void main(String[] args) {
		
		RationaleZahl bruch1 = new RationaleZahl(0,0);
		RationaleZahl bruch2 = new RationaleZahl(0,0);
		ArrayList<String> rechnungListe = new ArrayList<String>();
		int durchlauf = 1;
		
		do{
			bruch1 = Rechnung.einlesen();
			Rechnung.operation();
			bruch2 = Rechnung.einlesen();
			if(Rechnung.getOperator().equals("+")) {
				System.out.println(Rechnung.addieren(bruch1, bruch2));
				rechnungListe.add(Rechnung.addieren(bruch1, bruch2));
			}
			if(Rechnung.getOperator().equals("-")) {
				System.out.println(Rechnung.subtrahieren(bruch1, bruch2));
				rechnungListe.add(Rechnung.subtrahieren(bruch1, bruch2));
			}
			if(Rechnung.getOperator().equals("*")) {
				System.out.println(Rechnung.multiplizieren(bruch1, bruch2));
				rechnungListe.add(Rechnung.multiplizieren(bruch1, bruch2));
			}
			if(Rechnung.getOperator().equals("/")) {
				System.out.println(Rechnung.dividieren(bruch1, bruch2));
				rechnungListe.add(Rechnung.dividieren(bruch1, bruch2));
			}
			Rechnung.weiter();
			durchlauf++;
		}while(Rechnung.getWeiter().equals("j"));
		
		if(Rechnung.getWeiter().equals("n")) {
			System.out.println("--------Berechnet wurden--------");
			System.out.println(rechnungListe);
		}	
	}
}
```
Was meint ihr?


----------



## Final_Striker (1. Jul 2011)

Eine weitere Möglichkeit wäre es, wenn das Array voll ist, ein größeres Array zu erstellen und die Werte rüberkopieren.


----------



## Logaff (1. Jul 2011)

ich glaube nicht anders macht eine ArrayList....


----------



## Cottonwood (1. Jul 2011)

Du könntest auch einen Vector nehmen. Der ist dynamisch


----------



## HoaX (1. Jul 2011)

Cottonwood hat gesagt.:


> Du könntest auch einen Vector nehmen. Der ist dynamisch



Ein Vector ist nichts anderes als ne ArrayList mit synchronisierten Methoden - und deprecated. Lasst die Toten ruhen!


----------



## The_Virus (1. Jul 2011)

Final_Striker hat gesagt.:


> ...wenn das Array voll ist, ein größeres Array zu erstellen und die Werte rüberkopieren.


Ich hab mich da nochmal eingelesen, und Logaff hat Recht, die ArrayList macht genau das. Denn sie hat intern ein Array mit bestimmter Größe, legt ein neues größeres an, wenn das erste voll ist, und kopiert die Werte ins neue Array.

Daher werde ich doch bei der Arraylist bleiben. Das ist nicht nur deutlich einfacher, weil es mir die "Arbeit abnimmt", sondern auch viel eleganter, weil es weniger Code ist.


----------



## Empire Phoenix (1. Jul 2011)

Kann es evtl sein das es sinn der Aufgabe ist eben die ArrayList logic nachzuprogramieren?


----------



## The_Virus (1. Jul 2011)

Unsere Professorin ist da nicht so streng. Solange ich erklären kann, was die ArrayList macht und wie ich das in einem Code verwende, dürfen wir das auch verwenden. Denn wir müssen alle unsere Aufgaben präsentieren, ihr den gesamten Code erklären und vorführen.

Aber rein aus Interesse, wie würde ich denn diese ArrayList Logik selbst programmieren? Also wann weiß das Array, dass es voll ist? 
Neues Array anlegen und Werte rüber kopieren sollte ja kein Problem sein. Aber woher weiß das neue Array, an welcher Stelle es dann fortsetzen soll?


----------



## Andi_CH (1. Jul 2011)

Ein Quick and dirty Ansatz


```
public class ArrayDemo {

	private int[] arr;
	private int lastSet;
	private final int capInc;

	ArrayDemo(int initialCapacity, int capacityIncrement) {
		arr = new int[initialCapacity];
		lastSet = -1;
		capInc = capacityIncrement;
	}

	public void add(int i) {
		if (lastSet == arr.length-1) {
			int[] tmp = new int[arr.length+capInc];
			System.arraycopy(arr, 0, tmp, 0, arr.length);
			arr = tmp;
		}
		arr[++lastSet] = i;
	}

	@Override
	public String toString() {
		String retVal = "[ ";
		for (int i=0; i<=lastSet; i++) {
			retVal += i + " ";
		}
		retVal += "]";
		return retVal;
	}

	public static void main(String[] args) {
		ArrayDemo arrd = new ArrayDemo(1, 2);
		for (int i=0; i<5; i++) {
			arrd.add(i);
			System.out.println(arrd);
		}
	}
}
```

Ein wesentlich besseres Beispiel, das aber möglicherweise nicht so einfach zu verstehen ist, findest du wohl im Sourceode der ArrayList


----------



## The_Virus (1. Jul 2011)

Danke für deine Lösung, dennoch verstehe ich sie nicht so ganz. Ist mir irgendwie zu komplex, zu viele Variablen.
Da bleib ich doch lieber bei ArrayList.


----------



## Gast2 (1. Jul 2011)

Der spannende Teil ist der hier:

```
if (lastSet == arr.length-1) {
            int[] tmp = new int[arr.length+capInc];
            System.arraycopy(arr, 0, tmp, 0, arr.length);
            arr = tmp;
        }
```
In der ArrayList passiert das ähnlich, nur dass da meines Wissens nach mit nem Faktor multipliziert wird.
Analog wird das Array wieder verkleinert wenn wenig werte drin stehen.


----------



## The_Virus (1. Jul 2011)

was bedeudet "arr = tmp" ?
Wird arr dabei mit dem neuen Array tmp überschrieben?

Hab den speziellen Teil mal übernommen und es läuft auch irgendwie. Das Programm kann zwei Rechnungen speichern, obwohl das erste Array nur einen Speicherplatz hat. Dennoch kommt danach ein NullPointerException.

```
package paketRationaleZahlen_Test;

public class Start_Test {

	public static void main(String[] args) {
		
		RationaleZahl_Test bruch1 = new RationaleZahl_Test(0,0);
		RationaleZahl_Test bruch2 = new RationaleZahl_Test(0,0);
		String[] rechListe = new String[1];
		int durchlauf = 0; // Zaehler, wie viele Werte geschrieben wurden
		
		do{
			bruch1 = Rechnung_Test.einlesen();
			Rechnung_Test.operation();
			bruch2 = Rechnung_Test.einlesen();
			// geänderter Teil
			if(durchlauf >= rechListe.length) {
				String[] tempListe = new String[rechListe.length + 1];
				System.arraycopy(rechListe, 0, tempListe, 0, rechListe.length);
				rechListe = tempListe;
			} //bis hier		
			if(Rechnung_Test.getOperator().equals("+")) {	
				rechListe[durchlauf] = Rechnung_Test.addieren(bruch1, bruch2);
				System.out.println(rechListe[durchlauf]);
			}
			if(Rechnung_Test.getOperator().equals("-")) {
				rechListe[durchlauf] = Rechnung_Test.subtrahieren(bruch1, bruch2);
				System.out.println(rechListe[durchlauf]);
			}
			if(Rechnung_Test.getOperator().equals("*")) {
				rechListe[durchlauf] = Rechnung_Test.multiplizieren(bruch1, bruch2);
				System.out.println(rechListe[durchlauf]);
			}
			if(Rechnung_Test.getOperator().equals("/")) {
				rechListe[durchlauf] = Rechnung_Test.dividieren(bruch1, bruch2);
				System.out.println(rechListe[durchlauf]);
			}
			durchlauf++;
			Rechnung_Test.weiter();
		}while(Rechnung_Test.getWeiter().equals("j"));
		
		if(Rechnung_Test.getWeiter().equals("n")) {
			System.out.println("--------Berechnet wurden--------");
			for(int i = 0; i < durchlauf; i++) {
				System.out.println(rechListe[i]);
			}
		}	
	}
}
```


----------



## Andi_CH (1. Jul 2011)

Na wenn das schon zu komplex ist, viel Spass für die Zukunft ....

Also was 
	
	
	
	





```
arr
```
 ist, dürfte ja klar sein. Das ist die Referenz auf den produktiven Array.
Wenn der voll ist, lege ich einen neuen Array an (Arraylist berechnet die neue Länge natürlich etwas komplexer) Die Referenz 
	
	
	
	





```
tmp
```
 zeigt da drauf (ich brauche ja den alten noch, weil da die Werte drin stehen)
Dann kopiere ich den Inhalt von arr nach tmp.

Die Zeile 
	
	
	
	





```
arr = tmp
```
 bewirkt nur, dass die Referenz arr jetzt auf den neuen Array zeigt.
Der Alte liegt noch im Speicher herum, wird aber bei nächster Gelegenheit vom GarbageCollector weggeräumt.


```
lastSet
```
 oder etwas ähnliches brauchst du zwingend auch, sonst weisst du ja nicht wieviele Element du schon geschrieben hast und 
	
	
	
	





```
capInc
```
 ist keine Variablen sondern Konstanten die das Testen vereinfacht - die Anfangsgrösse und das Inkrement würde ich natürlich niemals so klein wählen, aber es hilft beim Testen.

Das erstens für das Verständnis und zweitens falls du doch Array verwenden müsstest.

ArrayList ist natürlich so nett und führt das alles schön brav mit, ist also sicher besser geeignet für dich, ausser eben das Ziel der Übung wäre genau diesen Mechanismus zu implementieren um ihn zu verstehen.


----------



## The_Virus (1. Jul 2011)

Danke nochmal für deine Erklärung. Ich hab meine main() nun korrigiert und es läuft genau so, wie ich mir das vorgestellt hatte. Diesen Teil hab ich hinzugefügt:

```
if(durchlauf >= rechListe.length) {
	String[] tempListe = new String[rechListe.length + 1];
	System.arraycopy(rechListe, 0, tempListe, 0, rechListe.length);
	rechListe = tempListe;
}
```


```
durchlauf
```
 ist bei mir der Zaehler, wie bei dir 
	
	
	
	





```
lastSet
```
.


----------



## Cottonwood (3. Jul 2011)

HoaX hat gesagt.:


> Ein Vector ist ... deprecated. Lasst die Toten ruhen!



Wo steht, dass Vector deprecated ist? Unter Vector steht das nicht: Vector (Java Platform SE 6)

Und unter Deprecated Classes taucht Vector nicht auf: Deprecated List (Java Platform SE 6)


----------



## fastjack (3. Jul 2011)

Vector ist auch nicht deprecated. Vector ist halt eine synchroniserte Liste. Das letzte was der Vector genießen durfte war die Implementierung des List-Interfaces.


----------

