Datenstrukturen in Java

Werbung
Java
Programmierung mit
Datenstrukturen
> Datenstrukturen
in Java
Mark Egloff 2006
1
Java
Programmierung mit
Lernziel Heute Abend
>
Sie lernen verschieden Datenstrukturen und Ihre Bedeutung
kennen z.B. „Arrays, Listen, Bäume, Maps“
>
Sie kennen die Unterschiede und wissen wann welche
Datenstruktur vorteilhaft eingesetzt werden sollte
>
Sie können eigene Datenstrukturen erstellen, diese sortieren
und entsprechend bearbeiten
Mark Egloff 2006
2
Java
Programmierung mit
Datenstrukturen in Java
Was sind „Datenstrukturen“?
>
Effiziente Algorithmen und Datenstrukturen bilden ein zentrales
Thema der Informatik. Es haben sich mittlerweile Standards
gebildet, die in allen Programmiersprachen vertreten sind.
>
In der Informatik bedeutet eine Datenstruktur eine bestimmte Art,
Daten zu verwalten und zu verknüpfen. Daten werden dabei in
einer bestimmten Struktur angeordnet um in geeigneter Weise
darauf zuzugreifen und diese dann bearbeiten zu können.
>
Datenstrukturen sind immer auf einen Anwendungsbereich
zugeschnitten, um den Zugriff und Manipulation entsprechend
effizient zu gestalten und abhandeln zu können.
Mark Egloff 2006
3
Java
Programmierung mit
Datenstrukturen in Java
Übersicht Datenstrukturen
>
Arrays
Mehrdimensionale Felder um Werte oder Objekte in einer festen Reihenfolge aufzunehmen. Die maximale Grösse ist festgelegt
>
Liste
Die Liste ist eine Datenstruktur zur dynamischen Speicherung von beliebig
vielen Objekten. Objekte werden dabei einer Reihe nach abgelegt
>
Bäume
Mehrere Elemente können auf andere Elmente verweisen. So entstehen
Verknüpfungen und es können „Bäume“ realisiert werden
>
Maps (Hashtabellen)
„Maps“ sind Indexstrukturen, die die Elemente anhand eines Indexes oder
Schlüssels verwalten
Mark Egloff 2006
4
Java
Programmierung mit
Datenstrukturen in Java
Übersicht Datenstrukturen in Java
>
Java kennt die meisten grundlegenden Datenstrukturen und bietet
entsprechende Klassen und Hilfsklassen hierzu an.
> „java.util.Arrays“ : Hilfsklasse zur Bearbeitung von Arrays
> „java.util.Collection“: Basisklasse für alle Arten von Datenstrukturen
> „java.util.Collections“: Hilfsklasse zur Bearbeitung von Strukturen
> „java.util.List“: Basisklasse für alle Arten von Listen
> „java.util.Set“: Basisklasse für alle Arten von sogenannten „Sets“
> „java.util.Map“: Basisklasse für alle Arten von indexierten Strukturen
>
Java kennt keine direkte Unterstützung für Bäume, hier müssen
entsprechend eigene Klassen oder Klassen von Drittanbietern
eingesetzt werden
Mark Egloff 2006
5
Java
Programmierung mit
Datenstrukturen
> Arrays in Java
Mark Egloff 2006
6
Java
Programmierung mit
Datenstrukturen in Java
Arrays
>
Ein Array (auch „Feld“ oder „Reihung“ genannt) ist ein spezieller
Datentyp, der mehrere Werte zu einer Einheit zusammenfasst, die über
einen ganzzahligen Index angesprochen werden können.
>
Er ist vergleichbar mit einem Setzkasten, in dem die Plätze
durchnummeriert sind. Jeder Platz (etwa für Schlümpfe) nimmt immer
Werte des gleichen Typs auf (nur Schlümpfe und keine Pokemons).
>
Die Grösse eines Arrays ist streng fixiert, sie wird bei der Erzeugung
eines Arrays festgelegt. Normalerweise liegen die Plätze eines Arrays
(seine Elemente) im Speicher hintereinander.
Mark Egloff 2006
1
2
3
4
5
6
7
8
9
7
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Deklarierung
>
In Java gehören Arrays zum Grundsyntax der Sprache. Ein Array kann
mit der einfachen Angabe durch „[]“ bei der Deklarierung einer Variable
bzw. eines Objektes angegeben werden.
>
Die Angabe „[]“ kann nach dem Datentyp erfolgen oder nach dem
Bezeichner, dies ergibt keinen Unterschied
>
Arrays können mehrdimensional sein. Hierbei wird für jede Dimension
einfach eine entsprechende Dimension mit „[]“ angegeben.
Syntax:
Datentyp[]
Datentyp
bezeichner;
bezeichner[][];
z.B: Deklarierung Arrays
int[]
aSimpleIntArray;
Kreis[][]
a2DCircleArray;
Mark Egloff 2006
8
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Instanzierung (1/3)
>
Arrays werden in Java als komplexe Datentypen gehandhabt. Sie
müssen nach der Deklarierung instanziert werden, bevor sie erstmals
verwendet werden können.
>
Für die Instanzierung hat man zwei Möglichkeiten. Entweder mittels
„new Typ[n]“ wird gleich die feste Grösse angegeben oder man gibt
eine Aufzählung der Elemente an, mittels „{}“ und mit Komas getrennt.
z.B: Instanzierung eines Arrays
String[] wochentage
= new String[7];
String[] laender;
// keine Instanzierung nur Deklaration
laender[0] = "CH";
 Compilerfehler
int[]
primZahlen
= { 1, 2, 3, 5, 7, 11 };
String[] substantive = {"Beware", "of", "the", "Dog"};
Mark Egloff 2006
9
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Instanzierung (2/3)
>
Arrays elementarer Datentypen werden bei der Instanzierung sofort mit
Werten initialisiert (entweder mit 0 oder mit false bei boolean)
>
Bei komplexen Datentypen sind die einzelnen Positionen Referenzen,
welche mit „null“ initialisiert sind. Diese Positionen müssen zuerst mit
einem entsprechendem Objekt belegt werden.
z.B: Deklarierung und Instanzierung eines Arrays m. komplexen Datentypen
Kreis[] kArray = new Kreis[100];
System.out.println( kArray[20] );
//  null
kArray[20] = new Kreis(2.5f);
System.out.println( kArray[20].getRadius() );
System.out.println( kArray[20] );
Mark Egloff 2006
//  Kreis: radius = 2.5f
10
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Instanzierung (3/3)
>
Der Aufbau von zweidimensionalen Feldern ist vergleichbar mit einer
Matrix beziehungsweise Tabelle.
>
Ebenso wie bei eindimensionalen Feldern lassen sich mehrdimensionale
Felder gleich beim Anlegen initialisieren
z.B: Deklarierung und Instanzierung eines multidimensionalen Arrays
int[][] schachbrett = new int[8][8]; // Alle 64 Plätze sind 0
int[][] A3x2 = {{1,2}, {2,3}, {3,4}};
char[][] B232 = {{'A','B'}, {'C','D','E'}, {'F','G'}};
1
2
A
B
2
3
C
D
3
4
F
G
System.out.print( A3x2[1][1]); // 3
E
System.out.print( B232[1][2]); // E
Mark Egloff 2006
11
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Zugriff auf die Elemente (1/2)
>
Der Zugriff auf die Elemente eines Felds erfolgt mit Hilfe der eckigen
Klammern „[n]“ und einer int-Positionsnummer (Indexnummer), die hinter
die Referenz an das Array-Objekt gesetzt werden.
>
In Java beginnt ein Array beim Index 0. Da die Elemente eines Arrays
ab 0 nummeriert werden, ist der letzte gültige Index um 1 kleiner als
die Länge des Felds. Bei einem Array a der Länge n ist der gültige
Bereich somit a[0] bis a[n-1].
z.B: Zugriff auf ein Element im Array
int[][]
schachbrett = new int[8][8];
schachbrett[4][5] = 38;
String[] substantive = {"Beware", "of", "the", "Dog"};
System.out.println( substantive[2] );
Mark Egloff 2006
 "the"
12
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Zugriff auf die Elemente (2/2)
Wird bei der Laufzeit über die Arraygrenze hinausgegriffen
wird eine „IndexOutOfBoundsException“ erzeugt
Wer bei einem nicht instanzierten Array auf ein Feld zugreift
riskiert eine „NullPointerException“


z.B: Zugriff auf falschen Array Index und nicht initialisierter Array
int[][] schachbrett = new int[8][8];
schachbrett[8][8] = 64;
String[] substantive = null;
System.out.println( substantive[2] );
Mark Egloff 2006
  Laufzeit Fehler !!!
  Laufzeit Fehler !!!
13
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Länge eines Arrays ermitteln
>
Die Anzahl der Elemente, die ein Array aufnehmen kann, wird Größe
beziehungsweise Länge genannt
>
Jedes Array-Objekt besitzt eine frei zugänglichen Objektvariable
„length“ die abgefragt werden kann. „length“ ist eine public final
int-Variable, deren Wert entweder positiv oder 0 ist. Die Größe lässt
sich nach der Instanzierung nicht mehr ändern.
z.B: Länge eines Arrays ermitteln
int[] primZahlen = { 1, 2, 3, 5, 7, 11 };
System.out.println( primZahlen.length );
primZahlen.length = 100;
primZahlen[primZahlen.length] = 11;
Mark Egloff 2006
6
  Compilerfehler
 Laufzeitfehler
14
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Iteration durch ein Array
>
Wer durch jeden Platz eines Arrays durchgehen (=iterieren) will, nimmt
am besten die „for“ – Schleife. Auch hier gilt wieder Vorsicht mit dem
ersten und letzten Index des Arrays.
z.B: Iteration durch die Argumente der „main“ Methode
public static void main( String[] args ) {
for ( int i = 0; i < args.length; i++ )
System.out.println( args[i] );
}
>
Seit Java 1.5 gibt es eine vereinfachte Version der „for“-Schleife die
speziell für die Iteration durch Datenstrukturen entworfen wurde
for ( String arg : args )
System.out.println( arg );
Mark Egloff 2006
15
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Nicht „rechteckige“ Felder
>
Da in Java mehrdimensionale Arrays als Arrays von Arrays
implementiert sind, müssen diese nicht zwingend rechteckig sein. Jede
Zeile im Feld kann seine eigene Größe haben.
>
Die Abfrage jeder Reihen-Länge erfolgt mit „array[row].length“
z.B: Ein dreieckiges Array mit Zeilen der Länge 1, 2 und 3.
int[][] m = new int[3][];
for ( int i = 0; i < 3; i++ )
m[i] = new int[i+1];
for ( int i = 0; i < m.length; i++ ) {
for ( int j = 0; j < m[i].length; j++ )
System.out.print(m[i][j]);
System.out.println();
0
00
000
}
Mark Egloff 2006
16
Java
Programmierung mit
Datenstrukturen in Java
Arrays – String und Chars
>
Obwohl Strings in den meisten Programmiersprachen als einfache
Character-Arrays angesehen werden, ist dies in Java nicht der Fall.
 char[] != String

byte[] != String
z.B. Folgende Zeile endet in Compilerfehler
char[] s = "Java ist einfach!";
>
  Compilerfehler
Java bietet bei der Stringklasse entsprechende Methoden an um in
Arrays zu wandeln.
z.B. String in char-Array wandeln und zurück
z.B. String in byte-Array u. zurück
String s = "Java ist einfach!";
char[] c = s.toCharArray();
String p = new String( c );
String s = "Java!";
byte[] b = s.getBytes();
String p = new String(b);
Mark Egloff 2006
17
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Arrays sind Objekte
>
Arrays werden in Java als komplexe Datentypen angesehen. Sie werden
selber wie Objekte handgehabt und es gelten somit die gleichen
Gesetze für die Austauschbarkeit, das Kopieren und das Vergleichen
z.B: Array als Objekt handhaben, Rückwärtskompatibilität u. Casting
int[] iArray = {1,2,3,4,5};
Object
i1 = iArray;
Object[] i2 = iArray;
 Compilerfehler da int != Object

Kreis[]
Kreis
Object
Object[]
k1
k2
k3
k4
=
=
=
=
new Kreis[20];
k1;
 Compilerfehler da Kreis[] != Kreis
k1;
k1;



if (k3 instanceof Kreis[]) Kreis[] k5 = (Kreis[]) k3;
Mark Egloff 2006
18
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Vergleichen eines Array
>
Da Arrays in Java wie Objekte gehandhabt werden können steht auch
die „equals()“ Methode zur Verfügung („java.lang.Object“).
Die Methode ist allerdings unbrauchbar da Sie nur die
Referenzen vergleicht!
>
Um Arrays zu vergleichen, sollte man die statische Methode
„equals()“ aus der Hilfsklasse „java.util.Arrays“ verwenden.
Diese funktioniert auch für komplexe Datentypen richtig.

z.B: Falsches und richtiges Vergleichen bei Arrays
char[] abc1 = { 'a', 'b', 'c' };
char[] abc2 = { 'a', 'b', 'c' };
System.out.print( abc1.equals(abc2) );
  false!
System.out.print( Arrays.equals(abc1,abc2) );
 true
Mark Egloff 2006
19
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (1/6)
>
In Java können Arrays mittels der mitgelieferten „clone()“ Methode
kopiert werden. Da die bekannte Methode „clone()“ den Datentyp
„java.lang.Object“ zurückliefert ,muss nachträglich gecastet
werden
>
Dieses Klonen funktioniert nur mit elementaren Datentypen. Bei
Arrays mit komplexen Datentypen werden die einzelnen Feldinhalte
nicht kopiert, sondern nur ihre Referenzen. Somit hat man mehrere
Referenzen auf das gleiche Objekt

z.B: Klonen eines int- Arrays
int[] quelle = new int[ 6 ];
int[] ziel
= ( int[] ) quelle.clone();
Mark Egloff 2006
20
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (2/6)
>
Eine alternative zu „clone()“ findet man bei der Klasse
„java.lang.System“. Diese bietet eine statische Methode
„arraycopy()“ an. Diese erlaubt noch zusätzlich von wo bis wo
innerhalb des Arrays kopiert werden soll.
>
Dieses Klonen funktioniert auch hier nur mit elementaren Datentypen.
Bei Arrays mit komplexen Datentypen werden nur die Referenzen
kopiert

z.B: Klonen eines int- Arrays mittels „System.arraycopy()“
int[] quelle = { 1, 2, 3, 4 , 5 };
int[] ziel
= new int[ quelle.length ];
System.arraycopy(quelle, 0, ziel, 0, quelle.length-1);
Mark Egloff 2006
21
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (3/6)
z.B: Falsches Klonen eines Arrays mit komplexen Datentypen
Kreis[] kArr = new Kreis[5];
for( int i=0; i<kArr.length ; i++)
kArr[i] = new Kreis(i+1);
Kreis[] kDup1 = kArr;
kDup1[0] = new Kreis(3.0f);
System.out.println( kArr[0].radius );
// jeder Platz m. Kreisobj
// nur Kopie der Array Referenz
//  Kreis: radius=3


Kreis[] kDup2 = (Kreis[]) kArr.clone(); // Kopie aller Feldreferenzen
kDup2[0].radius = 99;
System.out.println( kArr[0].radius );
//  Kreis: radius=99
System.out.println( kDup2[0].radius ); //  Kreis: radius=99
Mark Egloff 2006
22
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (4/6)
z.B: richtiges Klonen eines Arrays mit komplexen Datentypen
Kreis[] kSrc = new Kreis[5];
for( int i=0; i<kSrc.length ; i++)
kSrc[i] = new Kreis(i+1); // jeden Platz mit eigenem Kreisobj belegen
...
Kreis[] kDest = new Kreis[kSrc.length];
// Klasse Kreis muss "clone()" Methode implementieren
for( int i=0; i<kSrc.length ; i++)
kDest[i] = (Kreis) kSrc[i].clone(); // jeden Platz kopieren
Das Beispiel zeigt, dass das Klonen eines solchen Arrays
umständlich ist. Deshalb zeigen die nächsten Folien wie man
es generisch abhandeln könnte
Mark Egloff 2006
23
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (5/6)
z.B: generisches „deep“-Klonen eines Arrays mit komplexen Datentypen (1/2)
public static Object[] cloneArray(Object[] arrSrc)
throws Exception
{
Object[] arrDest = arrSrc.clone(); // kopiert "echten" Typ
for( int i=0; i<arrSrc.length ; i++) {
if (arrSrc[i] instanceof Cloneable ) {
Class clazz = arrSrc[i].getClass();
java.lang.reflect.Method m = clazz.getMethod("clone");
arrDest[i] = m.invoke(arrSrc[i], null);
}
else
throw new CloneNotSupportedException(clazz.toString());
}
return arrDest;
}
Mark Egloff 2006
24
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Klonen eines Array (6/6)
z.B: generisches „deep“-Klonen eines Arrays mit komplexen Datentypen (2/2)
Kreis[] kSrc = new Kreis[5];
for( int i=0; i<kSrc.length ; i++)
kSrc[i] = new Kreis(i+1);
Kreis[] kClone = (Kreis[]) ArrayTools.cloneArray(kSrc);
Andere Möglichkeiten des Kopierens:
>
Eine alternative für das herkömmliche Klonen/Kopieren ist mittels
Objektserialisierung zu arbeiten. Hierbei werden Objekte in einen ByteStream geschrieben (z.B. als File) und dann wieder eingelesen. Somit
entsteht eine Kopie ( Thema Serialisierung folgt später)
>
z.B. http://javatechniques.com/public/java/docs/basics/faster-deep-copy.html
Mark Egloff 2006
25
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Hilfsklasse „java.util.Arrays“ (1/4)
>
Java bietet eine Hilfsklasse „java.util.Arrays“ an um die
Handhabung der Arrays zu vereinfachen. Sie stellt Methoden für die
Vergleichung, Stringwandelung, Initialisierung und Sortierung zur
Verfügung (leider nicht für das Klonen)
>
Die Klasse besteht nur aus statischen Methoden, es muss daher kein
Objekt von ihr instanziert werden.
z.B: Sortieren eines String Arrays und String Ausgabe
String[] sA = { "Java", "ist", "einfach!"};
Arrays.sort(sA);
 vorsicht, verändert Original
System.out.println(sA);
 [Ljava.lang.String;@360be0
System.out.println( Arrays.toString(sA) );
 [Java, einfach!, ist]
Mark Egloff 2006


26
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Hilfsklasse „java.util.Arrays“ (2/4)
Übersicht wichtigster Methoden
>
asList(a)
konvertiert den Array in eine Liste (java.util.List)
>
binarySearch( a, b)
Dursucht den Array bis der Wert gefunden wird und gibt Position zurück
>
deepEquals(a,b)
Vergleicht zwei Arrays und jedes einzelne Element. Ist dabei das Element
wiederum ein Array wird ebenfalls ein Vergleich durchgeführt
>
equals(a,b)
Vergleicht zwei Arrays und jedes einzelne Element. Verwendet aber von
jedem Element nur die „equals()“ Methode. Kein Vergleich v. Subarrays
Mark Egloff 2006
27
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Hilfsklasse „java.util.Arrays“ (3/4)
Übersicht wichtigster Methoden
>
fill(a,b)
Füllt ein Array bzw. jeden Platz mit dem angegebenen Wert ab
>
sort(a)
Sortiert die Elemente in einem Array. Kann auch für Objekte verwendet
werden. Bei eigenen Objekten müsste aber zusätzlich das Interface
„java.lang.Comparable“ in die Klasse implementiert werden
>
toString(a)
Erzeugt aus dem Array eine String-Repräsentation. Es wird dabei von
jedem Element die „toString()“ Methode aufgerufen.
Mark Egloff 2006
28
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Die Hilfsklasse „java.util.Arrays“ (4/4)
Elemente im Array suchen, „binarySearch()“ und „contains()“
>
Ist das Array sortiert, lässt sich mit „Arrays.binarySearch()“ eine
binäre Suche (Halbierungssuche) durchführen. Wenn das Feld unsortiert
ist, funktioniert das nicht und die Java-Bibliothek hat für diesen Fall keine
Funktion im Angebot  eine eigene Schleife muss her.
>
Es gibt aber noch eine andere Möglichkeit. Die Funktion
„Arrays.asList()“ dekoriert das Array als Liste vom Typ
„java.util.List“, was dann eine „contains()“-Methode anbietet.
z.B.: Teste, ob auf der Kommandozeile der Schalter „-?“ gesetzt ist:
if ( Arrays.binSearch( args, "-?" ) >= 0) ...
if ( Arrays.asList( args ).contains( "-?" ) ) ...
Mark Egloff 2006
29
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Übergabe von Arrays bei Methoden
>
Arrays werde als komplexe Datentypen angesehen. Bei der
Parameterübergabe wird demzufolge eine Referenz übergeben
>
Über die Referenz hat man Zugriff auf das Originalobjekt und kann
deshalb den Original-Array verändern
z.B.: Methode die den Original-Array verändert
public static void toUpperCase( String[] sArray ) {
for(int i = 0; i < sArray.length; i++ )
sArray[i] = sArray[i].toUpperCase();
}
Mark Egloff 2006
30
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Methoden mit variabler Argumentanzahl
>
Seit Java 1.5 gibt es nun die „direkte“ Möglichkeit eine beliebige Anzahl
von Parametern bei einer Methode zu übergeben.
>
Hierbei muss lediglich der Datentyp angegeben werden und mit „...“
abgekürzt. Der so übergeben Parameter funktioniert wie ein Array.
>
Ein Alternative hierzu wäre den Parameter als „java.lang.Object“ zu
übergeben. Dieser Typ kann ja alles annehmen wie wir gesehen haben
z.B.: Methode „max()“ mit beliebiger Anzahl an int-Argumenten :
public static int max( int... iArray ) {
int currentMax = Integer.MIN_VALUE;
for ( int e : iArray )
if ( e > currentMax )currentMax = e;
return currentMax;
}
Mark Egloff 2006
31
Java
Programmierung mit
Datenstrukturen in Java
Arrays – Rückgabe von Arrays bei Methoden
>
Arrays können bei einer Methode zurückgegeben werden. Bei der
Methodenrückgabe muss der entsprechende Datentyp angegeben
werden
z.B.: Produkt zweier Vektoren
public static int[] prod( int[] a, int[] b ) {
if (a.length != b.length)
throw new IllegalArgumentException(...);
int[] c = new int[ a.length ];
for(int i = 0; i < a.length; i++ )
c[i] = a[i] * b[i];
return c;
}
Mark Egloff 2006
32
Herunterladen