Datenstrukturen / Container in Java Mathematik / Algebraischer Datentyp / Containerklassen Enum-Klassen Arrays (Felder) = elementare Container Algorithmen mit Arrays Prof. Dr. E. Ehses, 2014 1
Mathematik / Algebraischer Datentyp / Container Algebraischer Datentyp: Produkt und Summe Produkt: Tupel = kartesisches Produkt, Menge, Folge, etc. (in Mathematik keine Arrays!) Summe (Alternativen, disjunktive Vereinigung): Aufzählung, Klassenhierarchie Beispiel: List[A] = Node(head: A, tail: List[A]) Nil (das ist ein Beispiel für eine rekursive Definition) Anmerkung: in der Mathematik gibt es unendliche Datenstrukturen. Diese lassen sich auch in einigen Programmiersprachen modellieren: Stream.from(2).filter(x => isprime(x)) (Man darf aber keine Ergebnisse erwarten, die von unendlich vielen Werten abhängen) Prof. Dr. E. Ehses, 2014 2
Enum Eine Enumklasse ist eine Klasse mit einer statisch festgelegten Menge von Objekten. Die Enum-Objekte sind über statische Variablen der Enumklasse global verfügbar. Enums sind (fast) normale Klassen. Für vordefinierte / ererbte Methoden s. Java-API (Enum, EnumSet, EnumMap). public enum Tag { MONTAG, DIENSTAG, MITTWOCH, DONNERSTAG, FREITAG, SAMSTAG, SONNTAG; private static final Set<Tag> ARBEITSTAGE = EnumSet.range(MONTAG, FREITAG); public static Set<Tag> arbeitstage() { return Collections.unmodifiableSet(ARBEITSTAGE); public boolean istarbeitstag() { return ARBEITSTAGE.contains(this); Prof. Dr. E. Ehses, 2014 3
Verwendung von Enums Tag heute = Tag.SAMSTAG; heute = Enum.valueOf(Tag.class, "SAMSTAG") ; for (Tag t : Tag.arbeitstage()) { System.out.println(t + ": " + t.ordinal()); for (Tag t : Tag.values())... for (int i = 0; i < Tag.values().length; i++) Prof. Dr. E. Ehses, 2014 4
Arrays Arrays sind dynamisch angelegte Objekte mit nummerierten Variablen Arrays sind gleichzeitig eine sehr effiziente Datenstruktur: Deklaration von Variablen mit Elementtyp [] int[] intarray; Erzeugen eines Objekts mit Elementtyp [Anzahl der Elemente] intarray = new int[1000]; Anzahl der Elemente: Referenz.length intarray.length Nummerierung Referenz[0] Referenz[Anzahl-1] intaray[0] intarray[intarray.length-1] Index = Nummer des Elements. Der Zugriff wird überprüft. Keine (richtig) mehrdimensionalen Arrays, aber Array von Array int[][] a = new int[2][3]; int[] b = a[1]; Der Speicherbereich eines Arrays ist zusammenhängend Der Zugriff erfolgt in konstanter Zeit Die Arraygröße lässt sich nach der Erzeugung nicht mehr ändern. (Die Größe gehört nicht zum Typ) Als gute Alternative werden Behälterklassen der Bibliothek verwendet. Prof. Dr. E. Ehses, 2014 5
Beispiele int summe(int[] a) // Summe aller Elemente int indexof(kunde[], int n, Kunde k) // Position eines Elements oder -1 // das Array enthält n Elemente int maximum(int[] a) // größtes Element Prof. Dr. E. Ehses, 2014 6
/** * Summe der Elemente eines Arrays. * @param a das Array * @return die Summe aller Arrayelemente static int summe(int[] a) { /* Ziel (n steht für a.length, s für summe()): * s = 0, wenn n = 0 * = a[0] +.. + a[n-1], sonst int s = 0; int i = 0; /* * Invariante der Berechnung (Bedeutung der Variablen): * s = 0, wenn i = 0 * s = a[0] +.. + a[i-1], sonst while (i!= a.length) { s += a[i]; i += 1; return s; Prof. Dr. E. Ehses, 2014 7
Summe mit for /** * Summe der Elemente eines Arrays. * @param a das Array * @return die Summe aller Arrayelemente static int summe(int[] a) { /* Ziel (n steht für a.length, s für summe()): * s = 0, wenn n = 0 * = a[0] +.. + a[n-1], sonst int s = 0; /* * Invariante der Berechnung (Bedeutung der Variablen): * s = 0, wenn i = 0 * s = a[0] +.. + a[i-1], sonst for (int i = 0; i < a.length; i++) // for (int x : a) s += a[i]; // s += x; return s; Prof. Dr. E. Ehses, 2014 8
/** * Position eines gesuchten Elements im Array. * Es wird davon ausgehangen, dass Kundenarrays keine null * enthalten und dass keine null gesucht wird. * @param a Array mit Kundendaten * @param n Anzahl der gespeicherten Daten * @param k gesuchtes Objektjekt * @return die Position im Array oder -1, wenn nicht vorhanden * @throws NullPointerException wenn k == null static int indexof(kunde[] a, int n, Kunde k) { /* Ziel mit 0 <= i < n: * -1, wenn für alle i a[i]!= k * i, wenn a[i] == k und für 0 <= j < i a[j]!= k * * Invariante: * k ist nicht in a[0].. a[i-1] for (int i = 0; i < n; i++) { if(k.equals(a[i]) return i; return -1; Prof. Dr. E. Ehses, 2014 9
/** * Maximales Element eines Arrays ganzer Zahlen. * @param a das Array mit der Länge > 0 * @return das maximale Feldelement * @throws IndexOutOfBoundsException wenn a die Länge 0 hat. static int maximum(int[] a) { /* Ziel(n): * mit n = a.length * m = a[i] für ein i mit 0 <= i < n und * m >= a[0].. a[n-1] * * Invariante = Ziel(i) int m = a[0]; // evtl. ArrayIndexOutOfBoundsException for (int i = 1; i < a.length; i++) { if (a[i] > m) m = a[i]; return m; Prof. Dr. E. Ehses, 2014 10
/** * Maximales Element eines Arrays ganzer Zahlen. * @param a das Array mit der Länge > 0 * @return das maximale Feldelement * @throws IllegalArgumentException wenn a die Länge 0 hat. static int maximum(int[] a) { /* Ziel(n): * mit n = a.length * m = a[i] für ein 0 <= i < n und * m >= a[0].. a[n-1] * * Invariante = Ziel(i) require(a.length!= 0, "die Feldlaenge darf nicht 0 sein"); int m = a[0]; for (int i = 1; i < a.length; i++) { if (a[i] > m) m = a[i]; return m; static void require(boolean requirement, String errormsg) { if (!requirement) throw new IllegalArgumentException(errorMsg); Prof. Dr. E. Ehses, 2014 11
Behälter können die Datenstruktur kapseln class KundenContainer { private Kunde[] backup = new Kunde[10]; private int size = 0; boolean add(kunde neuerkunde) { if (! this.contains(neuerkunde) ) // NullPointerException? ensurecapacity(); backup[size++] = neuerkunde; return true; else return false; private ensurecapacity() { if (size == backup.length) backup = Arrays.copyOf(backup, anzahl*2); boolean contains(kunde k) { return indexof(k)!= -1; // Methode analog zu indexof(backup, size, k)!!... Prof. Dr. E. Ehses, 2014 12
Behälterklassen s. Lerneinheit z.b. KundenContainer, KundenSet etc. Oder modularer mit der der Verwendung der Klassen LinkedList, ArrayList, HashSet,.. List<Kunde> container = new ArrayList<>(); new LinkedList<>(); Set<Kunde> set = new HashSet<>(); container.add(kunde); if (set.contains(k1)).. Das Problem ist aber, dass Java die funktionale Programmierung nicht unterstützt, so dass man am Ende doch einen Kundencontainer braucht. Prof. Dr. E. Ehses, 2014 13
Ausblick auf Java 9 oder Java 10 (hier aus Scala, gibt es ansatzweise schon in Java 8) private var container = Set[Kunde]() def kundeloeschen(): Unit = { println("kunde loeschen") val kdnr = askint("bitte Kundennummer eingeben") container.find(k => k.nr == kdnr) match { case Some(k) => container -= k println("kunde wurde geloescht") case None => println("kunde nicht gefunden") def printspezifisch(): Unit = { val adresse = askstring("bitte Adressse eingeben") println( container.filter(adresse == _.adresse).mkstring("\n") ) Prof. Dr. E. Ehses, 2014 14