In Ihren Java-Anwendungen arbeiten Sie in der Regel mit verschiedenen Arten von Objekten. Und Sie möchten möglicherweise Operationen wie Sortieren, Suchen und Iterieren auf diesen Objekten durchführen.

Vor der Einführung des Collections-Frameworks in JDK 1.2 hätten Sie Arrays und Vektoren verwendet, um eine Gruppe von Objekten zu speichern und zu verwalten. Aber sie hatten ihre eigenen Nachteile.

Das Java Collections Framework zielt darauf ab, diese Probleme zu überwinden, indem es leistungsstarke Implementierungen gängiger Datenstrukturen bereitstellt. Diese ermöglichen es Ihnen, sich auf das Schreiben der Anwendungslogik zu konzentrieren, anstatt sich auf Low-Level-Operationen zu konzentrieren.

Dann hat die Einführung von Generics in JDK 1.5 das Java Collections Framework erheblich verbessert. Generics ermöglichen es Ihnen, die Typsicherheit für in einer Sammlung gespeicherte Objekte durchzusetzen, was die Robustheit Ihrer Anwendungen erhöht. Weitere Informationen zu Java Generics finden Sie hier.

In diesem Artikel werde ich Sie durch die Verwendung des Java Collections Frameworks führen. Wir werden die verschiedenen Arten von Sammlungen wie Listen, Sets, Queues und Maps diskutieren. Ich werde auch eine kurze Erklärung ihrer wichtigsten Eigenschaften wie:

  • Interne Mechanismen

  • Umgang mit Duplikaten

  • Unterstützung für Nullwerte

  • Sortierung

  • Synchronisation

  • Leistung

  • Schlüsselmethoden

  • Gemeinsame Implementierungen

Wir werden auch einige Codebeispiele durchgehen, um ein besseres Verständnis zu erlangen, und ich werde auf die Collections-Utility-Klasse und ihre Verwendung eingehen.

Inhaltsverzeichnis:

  1. Verständnis des Java Collections Frameworks

  2. Java Collection-Schnittstellen

  3. Sammlungen Dienstprogrammklasse

  4. Schlussfolgerung

Verständnis des Java Collections Frameworks

Laut der Java Dokumentation heißt es: „Eine Sammlung ist ein Objekt, das eine Gruppe von Objekten darstellt. Ein Sammlungsframework ist eine vereinheitlichte Architektur zur Darstellung und Manipulation von Sammlungen.“

Im einfachen Sinne hilft das Java Collections Framework dabei, eine Gruppe von Objekten zu verwalten und Operationen effizient und organisiert durchzuführen. Es erleichtert die Entwicklung von Anwendungen, indem es verschiedene Methoden zum Umgang mit Objektgruppen bereitstellt. Sie können Objekte effektiv hinzufügen, entfernen, suchen und sortieren, indem Sie das Java Collections Framework verwenden.

Sammlungsschnittstellen

In Java spezifiziert eine Schnittstelle einen Vertrag, der von jeder Klasse erfüllt werden muss, die ihn implementiert. Dies bedeutet, dass die implementierende Klasse konkrete Implementierungen für alle in der Schnittstelle deklarierten Methoden bereitstellen muss.

Im Java Collections Framework erweitern verschiedene Sammlungsschnittstellen wie Set, List und Queue die Collection-Schnittstelle und müssen sich an den Vertrag halten, der von der Collection-Schnittstelle definiert ist.

Entschlüsselung der Java Collections Framework-Hierarchie

Schauen Sie sich dieses ordentliche Diagramm aus diesem Artikel an, das die Java-Collection-Hierarchie veranschaulicht:

Wir werden von oben beginnen und nach unten arbeiten, damit Sie verstehen können, was dieses Diagramm zeigt:

  1. Am Ursprung des Java Collections Frameworks befindet sich die Schnittstelle Iterable, die es Ihnen ermöglicht, über die Elemente einer Sammlung zu iterieren.

  2. Die Schnittstelle Collection erweitert die Schnittstelle Iterable. Das bedeutet, dass sie die Eigenschaften und das Verhalten der Schnittstelle Iterable erbt und ihr eigenes Verhalten zum Hinzufügen, Entfernen und Abrufen von Elementen hinzufügt.

  3. Spezifische Schnittstellen wie List, Set und Queue erweitern die Collection-Schnittstelle weiter. Jede dieser Schnittstellen hat andere Klassen, die ihre Methoden implementieren. Zum Beispiel ist ArrayList eine beliebte Implementierung der List-Schnittstelle, HashSet implementiert die Set-Schnittstelle usw.

  4. Die Map-Schnittstelle ist Teil des Java Collections Frameworks, erweitert jedoch nicht die Collection-Schnittstelle, im Gegensatz zu den oben genannten.

  5. Alle Schnittstellen und Klassen in diesem Framework gehören zum Paket java.util.

Hinweis: Eine häufige Quelle der Verwirrung im Java Collections Framework dreht sich um den Unterschied zwischen Collection und Collections. Collection ist ein Interface im Framework, während Collections eine Hilfsklasse ist. Die Klasse Collections bietet statische Methoden, die Operationen auf den Elementen einer Sammlung durchführen.

Java-Sammlungsschnittstellen

Jetzt sind Sie mit den verschiedenen Arten von Sammlungen vertraut, die das Fundament des Sammlungsframeworks bilden. Nun werden wir uns die Schnittstellen List, Set, Queue und Map genauer ansehen.

In diesem Abschnitt werden wir jede dieser Schnittstellen besprechen und dabei ihre internen Mechanismen erkunden. Wir werden untersuchen, wie sie mit doppelten Elementen umgehen und ob sie die Einfügung von Nullwerten unterstützen. Wir werden auch das Ordnen von Elementen während der Einfügung und ihre Unterstützung für Synchronisation verstehen, was sich mit dem Konzept der Thread-Sicherheit befasst. Dann werden wir einige wichtige Methoden dieser Schnittstellen durchgehen und abschließend gemeinsame Implementierungen und deren Leistung für verschiedene Operationen überprüfen.

Bevor wir beginnen, wollen wir kurz über Synchronisation und Leistung sprechen.

  • Synchronisation kontrolliert den Zugriff auf gemeinsam genutzte Objekte durch mehrere Threads, gewährleistet ihre Integrität und verhindert Konflikte. Dies ist entscheidend für die Aufrechterhaltung der Thread-Sicherheit.

  • Beim Auswählen eines Sammlungstyps ist ein wichtiger Faktor dessen Leistungsfähigkeit bei häufigen Operationen wie Einfügen, Löschen und Abrufen. Die Leistung wird in der Regel mit der Big-O-Notation ausgedrückt. Weitere Informationen dazu finden Sie hier.

Listen

Eine Liste ist eine geordnete oder sequentielle Sammlung von Elementen. Sie folgt einer nullbasierten Indizierung, die es ermöglicht, Elemente anhand ihrer Indexposition einzufügen, zu entfernen oder darauf zuzugreifen.

  1. Interne Mechanismen: Eine Liste wird intern entweder von einem Array oder einer verketteten Liste unterstützt, abhängig von der Art der Implementierung. Zum Beispiel verwendet ein ArrayList intern ein Array, während eine LinkedList eine verkettete Liste verwendet. Weitere Informationen zur LinkedList finden Sie hier. Eine Liste passt sich dynamisch an, wenn Elemente hinzugefügt oder entfernt werden. Die indizierungsbasierte Abfrage macht sie zu einem sehr effizienten Sammlungstyp.

  2. Duplikate: Duplikate sind in einer Liste erlaubt, was bedeutet, dass es mehr als ein Element in einer Liste mit demselben Wert geben kann. Jeder Wert kann basierend auf dem Index, unter dem er gespeichert ist, abgerufen werden.

  3. Null: Nullwerte sind auch in einer Liste erlaubt. Da Duplikate erlaubt sind, können auch mehrere Null-Elemente vorhanden sein.

  4. Sortierung: Eine Liste behält die Reihenfolge der Einfügung bei, was bedeutet, dass die Elemente in der gleichen Reihenfolge gespeichert werden, in der sie hinzugefügt wurden. Dies ist hilfreich, wenn Sie Elemente in genau der Reihenfolge abrufen möchten, in der sie eingefügt wurden.

  5. Synchronisierung: Eine Liste ist standardmäßig nicht synchronisiert, was bedeutet, dass sie keine integrierte Möglichkeit hat, den Zugriff durch mehrere Threads gleichzeitig zu handhaben.

  6. Schlüsselmethoden: Hier sind einige Schlüsselmethoden einer List-Schnittstelle: add(E element), get(int index), set(int index, E element), remove(int index) und size(). Schauen wir uns an, wie man diese Methoden mit einem Beispielprogramm verwendet.

     import java.util.ArrayList;
     import java.util.List;
    
     public class ListExample {
         public static void main(String[] args) {
             // Liste erstellen
             List<String> list = new ArrayList<>();
    
             // add(E element)
             list.add("Apfel");
             list.add("Banane");
             list.add("Kirsche");
    
             // get(int index)
             String zweitesElement = list.get(1); // "Banane"
    
             // set(int index, E element)
             list.set(1, "Heidelbeere");
    
             // remove(int index)
             list.remove(0); // Entfernt "Apfel"
    
             // size()
             int größe = list.size(); // 2
    
             // Liste ausgeben
             System.out.println(list); // Ausgabe: [Heidelbeere, Kirsche]
    
             // Größe der Liste ausgeben
             System.out.println(größe); // Ausgabe: 2
         }
     }
    
  7. Gängige Implementierungen: ArrayList, LinkedList, Vector, Stack

  8. Leistung: Typischerweise sind Einfüge- und Löschvorgänge sowohl in ArrayList als auch in LinkedList schnell. Das Abrufen von Elementen kann jedoch langsam sein, da Sie durch die Knoten traversieren müssen.

Vorgang ArrayList LinkedList
Einfügen Schnell am Ende – O(1) amortisiert, langsam am Anfang oder in der Mitte – O(n) Schnell am Anfang oder in der Mitte – O(1), langsam am Ende – O(n)
Löschen Schnell am Ende – O(1) amortisiert, langsam am Anfang oder in der Mitte – O(n) Schnell – O(1), wenn Position bekannt ist
Abrufen Schnell – O(1) für den zufälligen Zugriff Langsam – O(n) für den zufälligen Zugriff, da es eine Traversierung beinhaltet

Sets

Ein Set ist eine Art von Sammlung, die keine Duplikate zulässt und das Konzept einer mathematischen Menge repräsentiert.

  1. Interner Mechanism: Ein Set wird intern von einem HashMap unterstützt. Abhängig vom Implementierungstyp wird es entweder von einem HashMap, LinkedHashMap oder einem TreeMap unterstützt. Ich habe einen ausführlichen Artikel darüber geschrieben, wie ein HashMap intern funktioniert hier. Schau es dir unbedingt an.

  2. Duplikate: Da ein Set das Konzept einer mathematischen Menge repräsentiert, sind doppelte Elemente nicht erlaubt. Dies stellt sicher, dass alle Elemente einzigartig sind und die Integrität der Sammlung erhalten bleibt.

  3. Null: Es ist maximal ein Nullwert in einem Set erlaubt, da Duplikate nicht erlaubt sind. Dies gilt jedoch nicht für die TreeSet-Implementierung, bei der Nullwerte überhaupt nicht erlaubt sind.

  4. Ordering: Die Reihenfolge der Elemente in einem Set hängt von der Art der Implementierung ab.

    • HashSet: Die Reihenfolge ist nicht garantiert, und Elemente können an beliebiger Stelle platziert werden.

    • LinkedHashSet: Diese Implementierung erhält die Einfügereihenfolge, sodass Sie die Elemente in derselben Reihenfolge abrufen können, in der sie eingefügt wurden.

    • TreeSet: Elemente werden entsprechend ihrer natürlichen Reihenfolge eingefügt. Alternativ können Sie die Einfügereihenfolge durch Angabe eines benutzerdefinierten Vergleichs steuern.

  5. Synchronisation: Ein Set ist nicht synchronisiert, was bedeutet, dass Sie auf Konflikte bei Nebenläufigkeit stoßen könnten, wie beispielsweise Wettlaufsituationen, die die Datenintegrität beeinträchtigen können, wenn zwei oder mehr Threads gleichzeitig auf ein Set-Objekt zugreifen

  6. Schlüsselmethoden: Hier sind einige Schlüsselmethoden einer Set-Schnittstelle: add(E element), remove(Object o), contains(Object o) und size(). Schauen wir uns an, wie man diese Methoden anhand eines Beispielsprogramms verwendet.

     import java.util.HashSet;
     import java.util.Set;
    
     public class SetExample {
         public static void main(String[] args) {
             // Ein Set erstellen
             Set<String> set = new HashSet<>();
    
             // Elemente zum Set hinzufügen
             set.add("Apfel");
             set.add("Banane");
             set.add("Kirsche");
    
             // Ein Element aus dem Set entfernen
             set.remove("Banane");
    
             // Überprüfen, ob das Set ein Element enthält
             boolean enthältApfel = set.contains("Apfel");
             System.out.println("Enthält Apfel: " + enthältApfel);
    
             // Die Größe des Sets abrufen
             int größe = set.size();
             System.out.println("Größe des Sets: " + größe);
         }
     }
    
  7. Übliche Implementierungen: HashSet, LinkedHashSet, TreeSet

  8. Leistung: Set-Implementierungen bieten schnelle Leistung für grundlegende Operationen, mit Ausnahme eines TreeSet, bei dem die Leistung relativ langsamer sein kann, da die interne Datenstruktur das Sortieren der Elemente während dieser Operationen beinhaltet.

Operation HashSet LinkedHashSet TreeSet
Einfügen Schnell – O(1) Schnell – O(1) Langsamer – O(log n)
Löschen Schnell – O(1) Schnell – O(1) Langsamer – O(log n)
Abruf Schnell – O(1) Schnell – O(1) Langsamer – O(log n)

Warteschlangen

Ein Queue ist eine lineare Sammlung von Elementen, die verwendet wird, um mehrere Elemente vor der Verarbeitung zu halten, normalerweise gemäß der FIFO (First-In-First-Out)-Reihenfolge. Das bedeutet, dass Elemente an einem Ende hinzugefügt und am anderen Ende entfernt werden, sodass das zuerst hinzugefügte Element zuerst entfernt wird.

  1. Interne Mechanismen: Die internen Arbeitsweisen eines Queue können je nach spezifischer Implementierung unterschiedlich sein.

    • LinkedList – verwendet eine doppelt verkettete Liste zur Speicherung von Elementen, was bedeutet, dass Sie sowohl vorwärts als auch rückwärts traversieren können, was flexible Operationen ermöglicht.

    • PriorityQueue – wird intern von einem binären Heap unterstützt, was für Abrufoperationen sehr effizient ist.

    • ArrayDeque – wird mit einem Array implementiert, das sich beim Hinzufügen oder Entfernen von Elementen erweitert oder verkleinert. Hier können Elemente von beiden Enden der Warteschlange hinzugefügt oder entfernt werden.

  2. Duplikate: In einer Queue sind Duplikate erlaubt, was bedeutet, dass mehrere Instanzen desselben Wertes eingefügt werden können.

  3. Null: Sie können keinen Nullwert in eine Queue einfügen, da einige Methoden einer Queue per Design null zurückgeben, um anzuzeigen, dass sie leer ist. Um Verwirrung zu vermeiden, sind Nullwerte nicht erlaubt.

  4. Sortierung: Elemente werden nach ihrer natürlichen Reihenfolge eingefügt. Alternativ können Sie die Reihenfolge der Einfügung durch Angabe eines benutzerdefinierten Vergleichers steuern.

  5. Synchronisierung: Eine Queue ist standardmäßig nicht synchronisiert. Sie können jedoch eine ConcurrentLinkedQueue oder eine BlockingQueue-Implementierung verwenden, um die Thread-Sicherheit zu gewährleisten.

  6. Schlüsselmethoden: Hier sind einige Schlüsselmethoden einer Queue-Schnittstelle: add(E element), offer(E element), poll() und peek(). Schauen wir uns an, wie man diese Methoden anhand eines Beispielsprogramms verwendet.

     import java.util.LinkedList;
     import java.util.Queue;
    
     public class QueueExample {
         public static void main(String[] args) {
             // Erstellen einer Warteschlange mit LinkedList
             Queue<String> queue = new LinkedList<>();
    
             // add-Methode zum Einfügen von Elementen verwenden, wirft eine Ausnahme, wenn das Einfügen fehlschlägt
             queue.add("Element1");
             queue.add("Element2");
             queue.add("Element3");
    
             // offer-Methode zum Einfügen von Elementen verwenden, gibt false zurück, wenn das Einfügen fehlschlägt
             queue.offer("Element4");
    
             // Warteschlange anzeigen
             System.out.println("Warteschlange: " + queue);
    
             // Auf das erste Element schauen (ohne es zu entfernen)
             String firstElement = queue.peek();
             System.out.println("Blick: " + firstElement); // gibt "Element1" aus
    
             // Das erste Element abrufen (abrufen und entfernen)
             String polledElement = queue.poll();
             System.out.println("Umfrage: " + polledElement); // gibt "Element1" aus
    
             // Warteschlange nach der Umfrage anzeigen
             System.out.println("Warteschlange nach der Umfrage: " + queue);
         }
     }
    
  7. Gängige Implementierungen: LinkedList, PriorityQueue, ArrayDeque

  8. Leistung: Implementierungen wie LinkedList und ArrayDeque sind in der Regel schnell beim Hinzufügen und Entfernen von Elementen. Die PriorityQueue ist etwas langsamer, da sie Elemente basierend auf der festgelegten Prioritätsreihenfolge einfügt.

Operation LinkedList PriorityQueue ArrayDeque
Einfügen Schnell am Anfang oder in der Mitte – O(1), langsam am Ende – O(n) Langsamer – O(log n) Schnell – O(1), Langsam – O(n), wenn eine Größenänderung des internen Arrays erforderlich ist
Löschen Schnell – O(1), wenn die Position bekannt ist Langsamer – O(log n) Schnell – O(1), Langsam – O(n), wenn eine Größenänderung des internen Arrays erforderlich ist
Abrufen Langsam – O(n) für den Zugriff auf ein Element, da eine Traversierung erforderlich ist Schnell – O(1) Schnell – O(1)

Karten

Ein Map stellt eine Sammlung von Schlüssel-Wert-Paaren dar, wobei jedem Schlüssel ein einziger Wert zugeordnet ist. Obwohl Map Teil des Java-Collection-Frameworks ist, erweitert es nicht das Interface java.util.Collection.

  1. Interner Mechanismus: Eine Map arbeitet intern mit einer HashTable basierend auf dem Konzept des Hashings. Ich habe einen ausführlichen Artikel zu diesem Thema geschrieben, also lies ihn für ein tieferes Verständnis.

  2. Duplikate: Eine Map speichert Daten als Schlüssel-Wert-Paare. Hier ist jeder Schlüssel einzigartig, daher sind doppelte Schlüssel nicht erlaubt. Aber doppelte Werte sind erlaubt.

  3. Null: Da doppelte Schlüssel nicht erlaubt sind, kann eine Map nur einen null Schlüssel haben. Da doppelte Werte erlaubt sind, können mehrere Nullwerte vorhanden sein. In der TreeMap-Implementierung können Schlüssel nicht null sein, da sie die Elemente basierend auf den Schlüsseln sortiert. Nullwerte sind jedoch erlaubt.

  4. Reihenfolge: Die Reihenfolge der Einfügung in einer Map variiert je nach Implementierung:

    • HashMap – die Einfügereihenfolge ist nicht garantiert, da sie auf dem Konzept des Hashings basiert.

    • LinkedHashMap – die Einfügereihenfolge wird beibehalten und Sie können die Elemente in derselben Reihenfolge abrufen, in der sie in die Sammlung hinzugefügt wurden.

    • TreeMap – Elemente werden basierend auf ihrer natürlichen Reihenfolge eingefügt. Alternativ können Sie die Einfügereihenfolge steuern, indem Sie einen benutzerdefinierten Vergleicher angeben.

  5. Synchronisation: Eine Map ist standardmäßig nicht synchronisiert. Aber Sie können Collections.synchronizedMap() oder Implementierungen von ConcurrentHashMap verwenden, um Thread-Sicherheit zu erreichen.

  6. Schlüsselmethoden: Hier sind einige Schlüsselmethoden einer Map-Schnittstelle: put(K key, V value), get(Object key), remove(Object key), containsKey(Object key) und keySet(). Schauen wir uns an, wie man diese Methoden anhand eines Beispielsprogramms verwendet.

     import java.util.HashMap;
     import java.util.Map;
     import java.util.Set;
    
     public class MapMethodsExample {
         public static void main(String[] args) {
             // Erstellen einer neuen HashMap
             Map<String, Integer> map = new HashMap<>();
    
             // put(K key, V value) - Fügt Schlüssel-Wert-Paare in die Map ein
             map.put("Apple", 1);
             map.put("Banana", 2);
             map.put("Orange", 3);
    
             // get(Object key) - Gibt den mit dem Schlüssel verknüpften Wert zurück
             Integer value = map.get("Banana");
             System.out.println("Wert für 'Banana': " + value);
    
             // remove(Object key) - Entfernt das Schlüssel-Wert-Paar für den angegebenen Schlüssel
             map.remove("Orange");
    
             // containsKey(Object key) - Überprüft, ob die Map den angegebenen Schlüssel enthält
             boolean hasApple = map.containsKey("Apple");
             System.out.println("Enthält 'Apple': " + hasApple);
    
             // keySet() - Gibt eine Ansicht des Sets der in der Map enthaltenen Schlüssel zurück
             Set<String> keys = map.keySet();
             System.out.println("Schlüssel in Map: " + keys);
         }
     }
    
  7. Gängige Implementierungen: HashMap, LinkedHashMap, TreeMap, Hashtable, ConcurrentHashMap

  8. Leistung: Die Implementierung von HashMap wird hauptsächlich aufgrund ihrer effizienten Leistungseigenschaften verwendet, die in der untenstehenden Tabelle dargestellt sind.

Operation HashMap LinkedHashMap TreeMap
Einfügen Schnell – O(1) Schnell – O(1) Langsamer – O(log n)
Löschen Schnell – O(1) Schnell – O(1) Langsamer – O(log n)
Abrufen Schnell – O(1) Schnell – O(1) Langsamer – O(log n)

Collections Utility-Klasse

Wie am Anfang dieses Artikels hervorgehoben, verfügt die Collections-Hilfsklasse über mehrere nützliche statische Methoden, mit denen Sie häufig verwendete Operationen an den Elementen einer Sammlung durchführen können. Diese Methoden helfen Ihnen, den Boilerplate-Code in Ihrer Anwendung zu reduzieren und sich auf die Geschäftslogik zu konzentrieren.

Hier sind einige wichtige Funktionen und Methoden sowie eine kurze Erläuterung zu deren Verwendung:

  1. Sortierung: Collections.sort(List<T>) – Diese Methode wird verwendet, um die Elemente einer Liste in aufsteigender Reihenfolge zu sortieren.

  2. Suchen: Collections.binarySearch(List<T>, Schlüssel) – diese Methode wird verwendet, um nach einem bestimmten Element in einer sortierten Liste zu suchen und seinen Index zurückzugeben.

  3. Umgekehrte Reihenfolge: Collections.reverse(List<T>) – diese Methode wird verwendet, um die Reihenfolge der Elemente in einer Liste umzukehren.

  4. Min/Max Operationen: Collections.min(Collection<T>) und Collections.max(Collection<T>) – diese Methoden werden verwendet, um das Minimum und das Maximum von Elementen in einer Sammlung zu finden, jeweils.

  5. Synchronisierung: Collections.synchronizedList(List<T>) – diese Methode wird verwendet, um eine Liste threadsicher zu machen, indem sie synchronisiert wird.

  6. Unveränderbare Sammlungen: Collections.unmodifiableList(List<T>) – diese Methode wird verwendet, um eine schreibgeschützte Ansicht einer Liste zu erstellen und Änderungen zu verhindern.

Hier ist ein Beispiel für ein Java-Programm, das verschiedene Funktionalitäten der Hilfsklasse Collections demonstriert:

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionsExample {
    public static void main(String[] args) {
        List<Integer> numbers = new ArrayList<>();
        numbers.add(5);
        numbers.add(3);
        numbers.add(8);
        numbers.add(1);

        // Sortierung
        Collections.sort(numbers);
        System.out.println("Sorted List: " + numbers);

        // Suche
        int index = Collections.binarySearch(numbers, 3);
        System.out.println("Index of 3: " + index);

        // Umgekehrte Reihenfolge
        Collections.reverse(numbers);
        System.out.println("Reversed List: " + numbers);

        // Min-/Max-Operationen
        int min = Collections.min(numbers);
        int max = Collections.max(numbers);
        System.out.println("Min: " + min + ", Max: " + max);

        // Synchronisierung
        List<Integer> synchronizedList = Collections.synchronizedList(numbers);
        System.out.println("Synchronized List: " + synchronizedList);

        // Unveränderbare Sammlungen
        List<Integer> unmodifiableList = Collections.unmodifiableList(numbers);
        System.out.println("Unmodifiable List: " + unmodifiableList);
    }
}

Dieses Programm demonstriert Sortieren, Suchen, Umkehren, Finden von Mindest- und Höchstwerten, Synchronisieren und Erstellen einer unveränderbaren Liste mit der Hilfsklasse Collections.

Abschluss

In diesem Artikel haben Sie etwas über das Java Collections Framework gelernt und wie es dabei hilft, Gruppen von Objekten in Java-Anwendungen zu verwalten. Wir haben verschiedene Typen von Sammlungen wie Listen, Sets, Queues und Maps erkundet und Einblick in einige der wichtigsten Merkmale und wie jeder dieser Typen sie unterstützt, gewonnen.

Sie haben etwas über Leistung, Synchronisierung und wichtige Methoden gelernt und wertvolle Einblicke gewonnen, um die richtigen Datenstrukturen für Ihre Anforderungen auszuwählen.

Durch das Verständnis dieser Konzepte können Sie das Java Collections Framework vollständig nutzen, um effizienteren Code zu schreiben und robuste Anwendungen zu entwickeln.

Wenn Sie diesen Artikel interessant fanden, schauen Sie gerne meine anderen Artikel auf freeCodeCamp an und vernetzen Sie sich mit mir auf LinkedIn.