Part 3

Fortgeschrittene Programmierkonzepte

1. Erweiterte Fehlererkennung und Debugging-Techniken

Exception Handling und benutzerdefinierte Fehlerklassen

In der Programmierung ist es wichtig, nicht nur einfache Fehler zu erkennen, sondern auch auf unerwartete Situationen vorbereitet zu sein. Das Exception Handling in Java bietet Mechanismen, um solche Situationen zu kontrollieren und zu behandeln.

try {
    int result = 10 / 0;
} catch (ArithmeticException e) {
    System.out.println("Ein Fehler ist aufgetreten: " + e.getMessage());
}

Zusätzlich können Sie benutzerdefinierte Fehlerklassen erstellen, um spezifischere Fehler in Ihrem Programm zu behandeln.

class InvalidAgeException extends Exception {
    public InvalidAgeException(String message) {
        super(message);
    }
}

public void setAge(int age) throws InvalidAgeException {
    if (age < 0) {
        throw new InvalidAgeException("Das Alter kann nicht negativ sein.");
    }
}

Unit Testing mit JUnit

JUnit ist ein weit verbreitetes Framework in Java zur Durchführung von Unit-Tests. Unit-Tests helfen, sicherzustellen, dass kleine, isolierte Teile Ihres Codes (Units) korrekt funktionieren.

import static org.junit.Assert.assertEquals;
import org.junit.Test;

public class CalculatorTest {

    @Test
    public void testAddition() {
        Calculator calc = new Calculator();
        assertEquals(5, calc.add(2, 3));
    }
}

2. Erweiterte Datenstrukturen

HashMaps und Sets

Neben Listen und Arrays sind HashMaps und Sets äußerst nützliche Datenstrukturen. Sie ermöglichen das Speichern von Schlüssel-Wert-Paaren und das Vermeiden von Duplikaten.

import java.util.HashMap;
import java.util.HashSet;

HashMap<String, Integer> ageMap = new HashMap<>();
ageMap.put("Alice", 30);
ageMap.put("Bob", 25);

HashSet<String> uniqueNames = new HashSet<>();
uniqueNames.add("Alice");
uniqueNames.add("Bob");
uniqueNames.add("Alice"); // Wird ignoriert, da Alice bereits vorhanden ist

Multidimensionale Arrays

Ein multidimensionales Array ist ein Array, das weitere Arrays als Elemente enthält. Diese Struktur ist nützlich, um Matrizen oder Tabellen abzubilden.

int[][] matrix = {
    {1, 2, 3},
    {4, 5, 6},
    {7, 8, 9}
};

for (int i = 0; i < matrix.length; i++) {
    for (int j = 0; j < matrix[i].length; j++) {
        System.out.print(matrix[i][j] + " ");
    }
    System.out.println();
}

3. Algorithmen zur Datenverarbeitung

Such- und Sortieralgorithmen

Effiziente Such- und Sortieralgorithmen sind entscheidend, wenn große Datenmengen verarbeitet werden müssen. Zu den gängigen Algorithmen gehören die binäre Suche und der Quicksort.

Binäre Suche

Die binäre Suche ist ein effizienter Algorithmus, um ein Element in einer sortierten Liste zu finden. Sie halbiert wiederholt den Suchbereich, bis das Element gefunden wird oder die Liste erschöpft ist.

public int binarySearch(int[] array, int target) {
    int low = 0;
    int high = array.length - 1;

    while (low <= high) {
        int mid = (low + high) / 2;
        if (array[mid] == target) {
            return mid;
        } else if (array[mid] < target) {
            low = mid + 1;
        } else {
            high = mid - 1;
        }
    }
    return -1; // Element nicht gefunden
}

Quicksort

Quicksort ist ein effizienter, rekursiver Sortieralgorithmus, der auf dem Divide-and-Conquer-Prinzip basiert.

public void quickSort(int[] array, int low, int high) {
    if (low < high) {
        int pivotIndex = partition(array, low, high);
        quickSort(array, low, pivotIndex - 1);
        quickSort(array, pivotIndex + 1, high);
    }
}

private int partition(int[] array, int low, int high) {
    int pivot = array[high];
    int i = (low - 1);
    for (int j = low; j < high; j++) {
        if (array[j] <= pivot) {
            i++;
            int temp = array[i];
            array[i] = array[j];
            array[j] = temp;
        }
    }
    int temp = array[i + 1];
    array[i + 1] = array[high];
    array[high] = temp;
    return i + 1;
}

4. Fortgeschrittene String-Verarbeitung

Reguläre Ausdrücke

Reguläre Ausdrücke sind Muster, die verwendet werden, um Text zu durchsuchen oder zu manipulieren. Sie sind ein mächtiges Werkzeug für die Arbeit mit Strings.

import java.util.regex.Pattern;
import java.util.regex.Matcher;

Pattern pattern = Pattern.compile("a*b");
Matcher matcher = pattern.matcher("aaaaab");
boolean matchFound = matcher.matches();

StringBuilder für effiziente String-Manipulation

Wenn viele String-Operationen durchgeführt werden, ist der Einsatz eines StringBuilder sinnvoll, da dieser im Gegensatz zu normalen Strings veränderbar ist und nicht jedes Mal ein neues Objekt erstellt wird.

StringBuilder sb = new StringBuilder();
sb.append("Hallo");
sb.append(" ");
sb.append("Welt!");
System.out.println(sb.toString());

Fazit

In diesem Abschnitt haben wir uns mit fortgeschrittenen Programmierkonzepten und Datenstrukturen auseinandergesetzt. Diese Themen sind entscheidend, um komplexere Programme zu schreiben und effizient mit größeren Datenmengen zu arbeiten.

Sie haben das Ende dieses Abschnitts erreicht!