Java - Datenstrukturen

Willkommen, zukünftige Programmierer! Heute tauchen wir in die aufregende Welt der Java-Datenstrukturen ein. Als dein freundlicher Nachbarschaftsinformatiklehrer bin ich hier, um dich auf dieser Reise Schritt für Schritt zu führen. Keine Sorge, wenn du neu im Programmieren bist – wir beginnen mit den Grundlagen und arbeiten uns hoch. Also, schnallt euch eure virtuellen Helme an und lassen uns mit dem Aufbau unseres Wissens beginnen!

Java - Data Structures

Einführung in Datenstrukturen

Bevor wir uns spezifischen Java-Datenstrukturen zuwenden, lassen wir uns erst einmal anschauen, was Datenstrukturen sind und warum sie wichtig sind.

Stellen wir uns vor, du organisierst eine Bibliothek. Du würdest sicherlich nicht alle Bücher in einen Haufen werfen, oder? Natürlich nicht! Du würdest sie auf eine Weise organisieren, die es einfach macht, sie zu finden und zu verwalten. Genau das machen Datenstrukturen für unsere Daten im Programmieren.

Datenstrukturen sind Weisen, Daten zu organisieren und zu speichern, damit wir sie effizient zugreifen und ändern können. In Java haben wir mehrere integrierte Datenstrukturen, die wir verwenden können, jede mit ihren eigenen Stärken und Anwendungsfällen.

Eingebaute Java-Datenstrukturen

Lassen wir uns einige der häufigsten Datenstrukturen in Java ansehen:

Die Enumeration

Eine Enumeration ist wie ein Automat, der nummerierte Tickets einzeln herausgibt. Es ist eine Schnittstelle in Java, die es uns ermöglicht, Elemente in einer Sammlung einzeln zuzugreifen.

Hier ist ein einfaches Beispiel:

import java.util.*;

public class EnumerationExample {
public static void main(String args[]) {
Vector<String> dayNames = new Vector<>();
dayNames.add("Montag");
dayNames.add("Dienstag");
dayNames.add("Mittwoch");

Enumeration<String> days = dayNames.elements();

while (days.hasMoreElements()) {
System.out.println(days.nextElement());
}
}
}

In diesem Beispiel erstellen wir einen Vector von Wochentagsnamen und verwenden Enumeration, um durch sie zu iterieren. Die Methode hasMoreElements() überprüft, ob es mehr Elemente gibt, und nextElement() ruft das nächste Element ab.

Das BitSet

Ein BitSet ist wie eine Reihe von Lichtschaltern – jeder kann entweder an (1) oder aus (0) sein. Es ist nützlich, wenn du eine Reihe von Wahr/Falsch-Werten effizient speichern musst.

Hier ist ein Beispiel:

import java.util.BitSet;

public class BitSetExample {
public static void main(String args[]) {
BitSet bits1 = new BitSet(16);
BitSet bits2 = new BitSet(16);

// setze einige Bits
for(int i = 0; i < 16; i++) {
if((i % 2) == 0) bits1.set(i);
if((i % 5) != 0) bits2.set(i);
}

System.out.println("Anfängliches Muster in bits1: " + bits1);
System.out.println("Anfängliches Muster in bits2: " + bits2);

// AND-Bits
bits2.and(bits1);
System.out.println("bits2 AND bits1: " + bits2);
}
}

Dieses Beispiel zeigt die Erstellung von BitSets, das Setzen von Bits und die Durchführung bitweiser Operationen.

Der Vector

Ein Vector ist wie ein magisches Array, das wachsen oder schrumpfen kann, je nachdem, was erforderlich ist. Es ist ähnlich wie eine ArrayList, aber synchronisiert, was es thread-sicher macht.

So könntest du einen Vector verwenden:

import java.util.*;

public class VectorExample {
public static void main(String args[]) {
Vector<Integer> vec = new Vector<>(3, 2);
System.out.println("Anfangsgröße: " + vec.size());
System.out.println("Anfangskapazität: " + vec.capacity());

vec.addElement(1);
vec.addElement(2);
vec.addElement(3);
vec.addElement(4);
System.out.println("Kapazität nach vier Hinzufügungen: " + vec.capacity());

vec.addElement(5);
System.out.println("Aktuelle Kapazität: " + vec.capacity());

System.out.println("Erstes Element: " + vec.firstElement());
System.out.println("Letztes Element: " + vec.lastElement());
}
}

Dieses Beispiel zeigt, wie man einen Vector erstellt, Elemente hinzufügt und seine Größe und Kapazität überprüft.

Der Stack

Ein Stack ist wie ein Stapel von Tellern – du kannst nur oben hinzufügen oder entfernen. Er folgt dem Last-In-First-Out (LIFO)-Prinzip.

Sehen wir uns einen Stack in Aktion an:

import java.util.*;

public class StackExample {
public static void main(String args[]) {
Stack<String> stack = new Stack<>();
stack.push("Unten");
stack.push("Mitte");
stack.push("Oben");

System.out.println("Stack: " + stack);
System.out.println("Gepoppt: " + stack.pop());
System.out.println("Stack nach pop: " + stack);
System.out.println("Spitze: " + stack.peek());
System.out.println("Stack nach peek: " + stack);
}
}

Dieses Beispiel zeigt das Hinzufügen von Elementen zu einem Stack, das Herausnehmen und das Ansehen des obersten Elements.

Das Dictionary

Ein Dictionary ist eine abstrakte Klasse, die eine Schlüssel-Wert-Datenstruktur darstellt. Es ist wie ein echtes Wörterbuch, bei dem jedes Wort (Schlüssel) eine Definition (Wert) hat.

Obwohl Dictionary abstrakt ist und nicht direkt instanziert werden kann, wird seine Unterklasse Hashtable häufig verwendet:

import java.util.*;

public class DictionaryExample {
public static void main(String args[]) {
Dictionary<String, String> dict = new Hashtable<>();

dict.put("Apfel", "Ein Obst");
dict.put("Java", "Eine Programmiersprache");
dict.put("Computer", "Ein elektronisches Gerät");

System.out.println("Dictionary: " + dict);
System.out.println("Wert für den Schlüssel 'Java': " + dict.get("Java"));

System.out.println("Schlüssel: ");
for (Enumeration<String> keys = dict.keys(); keys.hasMoreElements();) {
System.out.println(keys.nextElement());
}
}
}

Dieses Beispiel zeigt, wie man ein Dictionary (über Hashtable) verwendet, um Schlüssel-Wert-Paare zu speichern und abzurufen.

Das Hashtable

Hashtable ist wie ein super-effizientes Aktenvernichter. Es speichert Schlüssel-Wert-Paare und ermöglicht eine schnelle Wertesuche basierend auf ihren Schlüsseln.

Hier ist ein Beispiel für die Verwendung eines Hashtables:

import java.util.*;

public class HashtableExample {
public static void main(String args[]) {
Hashtable<String, Integer> numbers = new Hashtable<>();
numbers.put("eins", 1);
numbers.put("zwei", 2);
numbers.put("drei", 3);

System.out.println("Hashtable: " + numbers);
System.out.println("Wert von 'zwei': " + numbers.get("zwei"));
System.out.println("Ist 'vier' ein Schlüssel? " + numbers.containsKey("vier"));
System.out.println("Ist 3 ein Wert? " + numbers.containsValue(3));

numbers.remove("zwei");
System.out.println("Hashtable nach dem Entfernen von 'zwei': " + numbers);
}
}

Dieses Beispiel zeigt das Hinzufügen von Schlüssel-Wert-Paaren zu einem Hashtable, das Abrufen von Werten, das Überprüfen von Schlüsseln und Werten und das Entfernen von Einträgen.

Die Properties

Properties ist eine besondere Art von Hashtable, die String-Schlüssel-Wert-Paare speichert. Es wird oft für Konfigurationseinstellungen verwendet.

Sehen wir uns an, wie Properties funktioniert:

import java.util.*;

public class PropertiesExample {
public static void main(String args[]) {
Properties capitals = new Properties();
capitals.put("USA", "Washington D.C.");
capitals.put("Frankreich", "Paris");
capitals.put("Japan", "Tokyo");

System.out.println("Properties: " + capitals);
System.out.println("Hauptstadt von Frankreich: " + capitals.getProperty("Frankreich"));

// Setze einen Standardwert
System.out.println("Hauptstadt von Spanien: " + capitals.getProperty("Spanien", "Nicht gefunden"));

capitals.list(System.out);
}
}

Dieses Beispiel zeigt, wie man Properties verwendet, um String-Schlüssel-Wert-Paare zu speichern und abzurufen, mit einem Standardwert für fehlende Schlüssel.

Schlussfolgerung

Glückwunsch! Du hast gerade deine ersten Schritte in die Welt der Java-Datenstrukturen unternommen. Jede dieser Strukturen hat ihre eigenen einzigartigen Eigenschaften und Anwendungsfälle. Während du deine Programmierreise fortsetzt, wirst du feststellen, dass du verschiedene Strukturen je nach deinen spezifischen Bedürfnissen verwenden wirst.

Denke daran, dass die Wahl der richtigen Datenstruktur einen großen Unterschied machen kann, wie effizient dein Programm läuft. Es ist wie das Wahl des richtigen Werkzeugs für eine Aufgabe – ein Hammer ist großartig für Nägel, aber nicht so gut für Schrauben!

Weiter üben mit diesen Strukturen, versuche, sie in eigenen Projekten zu verwenden, und fürchte dich nicht, zu experimentieren. Frohes Coden!

Credits: Image by storyset