Beginnen Sie mit dem Java Collections Framework

JDK 1.2 führt ein neues Framework für Sammlungen von Objekten ein, das Java Collections Framework. "Oh nein", stöhnt du, "keine andere API, kein anderes Framework zum Lernen!" Aber warten Sie, bevor Sie sich abwenden, hören Sie mir zu: Das Collections-Framework ist Ihre Mühe wert und wird Ihrer Programmierung in vielerlei Hinsicht zugute kommen. Drei große Vorteile fallen sofort ein:

  • Es verbessert die Lesbarkeit Ihrer Sammlungen erheblich, indem es einen Standardsatz von Schnittstellen bereitstellt, die von vielen Programmierern in vielen Anwendungen verwendet werden können.
  • Es macht Ihren Code flexibler, indem Sie Schnittstellen anstelle konkreter Klassen übergeben und zurückgeben können, wodurch Ihr Code verallgemeinert wird, anstatt ihn zu sperren.
  • Es bietet viele spezifische Implementierungen der Schnittstellen, sodass Sie die Sammlung auswählen können, die am besten passt und die höchste Leistung für Ihre Anforderungen bietet.

Und das ist nur für den Anfang.

Unsere Tour durch das Framework beginnt mit einem Überblick über die Vorteile, die es für die Speicherung von Objektgruppen bietet. Wie Sie bald feststellen werden, werden Ihre Programme einheitlich und präzise sein , da Ihre alten Arbeitspferdefreunde Hashtableund Vectordie neue API unterstützen - etwas, worüber Sie und die Entwickler, die auf Ihren Code zugreifen, sicherlich jubeln werden.

Nach unserer Vorbesprechung werden wir uns eingehender mit den Details befassen.

Der Vorteil von Java Collections: Ein Überblick

Bevor Collections sein willkommenstes Debüt feierte, waren die Standardmethoden zum Gruppieren von Java-Objekten über das Array, das Vectorund das Hashtable. Alle drei dieser Sammlungen haben unterschiedliche Methoden und Syntax für den Zugriff auf Mitglieder: Arrays verwenden die Symbole in eckigen Klammern ([]), Vectorverwenden die elementAtMethode sowie HashtableVerwendungen getund putMethoden. Diese Unterschiede haben Programmierer lange Zeit auf den Weg zu Inkonsistenzen bei der Implementierung ihrer eigenen Sammlungen geführt - einige emulieren die VectorZugriffsmethoden und andere die EnumerationSchnittstelle.

Um die Sache noch weiter zu verkomplizieren, werden die meisten VectorMethoden als endgültig markiert. Das heißt, Sie können die VectorKlasse nicht erweitern , um eine ähnliche Art von Sammlung zu implementieren. Wir könnten eine Auflistungsklasse erstellen, die wie eine Vectoraussieht und sich wie eine verhält Vector, aber nicht an eine Methode übergeben werden kann, die a Vectorals Parameter verwendet.

Schließlich implementiert keine der Sammlungen (Array Vectoroder Hashtable) eine Standardzugriffsschnittstelle für Mitglieder. Als Programmierer Algorithmen (wie Sortierungen) entwickelten, um Sammlungen zu manipulieren, brach ein hitziger Diskurs darüber aus, welches Objekt an den Algorithmus übergeben werden sollte. Sollten Sie ein Array oder ein übergeben Vector? Sollten Sie beide Schnittstellen implementieren? Sprechen Sie über Doppelarbeit und Verwirrung.

Glücklicherweise behebt das Java Collections Framework diese Probleme und bietet eine Reihe von Vorteilen gegenüber der Verwendung ohne Framework oder der Verwendung von Vectorund Hashtable:

  • Ein verwendbarer Satz von Sammlungsschnittstellen

    Durch eine der grundlegenden Schnittstellen Implementierung - Collection, Set, Listoder Map- Sie Ihre Klasse Konform eine gemeinsame API gewährleisten und wird regelmäßigere und leicht verständlich. Unabhängig davon, ob Sie eine SQL-Datenbank, einen Farbmuster-Matcher oder eine Remote-Chat-Anwendung implementieren Collection, sind die Vorgänge für Ihre Objektsammlung Ihren Benutzern bekannt , wenn Sie die Schnittstelle implementieren . Die Standardschnittstellen vereinfachen auch das Übergeben und Zurückgeben von Sammlungen an und von Klassenmethoden und ermöglichen es den Methoden, an einer größeren Vielfalt von Sammlungen zu arbeiten.

  • Ein grundlegender Satz von Sammlungsimplementierungen

    Zusätzlich zu den vertrauenswürdigen Hashtableund Vector, die aktualisiert wurden, um die CollectionSchnittstellen zu implementieren , wurden neue Sammlungsimplementierungen hinzugefügt, einschließlich HashSetund TreeSet, ArrayListund LinkedList, und HashMapund Map. Durch die Verwendung einer vorhandenen, allgemeinen Implementierung wird Ihr Code kürzer und schneller heruntergeladen. Durch die Verwendung des vorhandenen Core-Java-Code-Core wird sichergestellt, dass Verbesserungen am Basiscode auch die Leistung Ihres Codes verbessern.

  • Andere nützliche Verbesserungen

    Jede Sammlung gibt jetzt Iteratoreinen verbesserten Typ zurück Enumeration, der Elementoperationen wie das Einfügen und Löschen ermöglicht. Das Iteratorist "ausfallsicher", was bedeutet, dass Sie eine Ausnahme erhalten, wenn die Liste, die Sie durchlaufen, von einem anderen Benutzer geändert wird. Listenbasierte Sammlungen wie " Vectorreturn a" ListIteratorermöglichen außerdem eine bidirektionale Iteration und Aktualisierung.

    Mehrere Sammlungen ( TreeSetund TreeMap) unterstützen implizit die Bestellung. Verwenden Sie diese Klassen, um mühelos eine sortierte Liste zu führen. Sie können die kleinsten und größten Elemente finden oder eine binäre Suche durchführen, um die Leistung großer Listen zu verbessern. Sie können andere Sammlungen sortieren, indem Sie eine Sammlungsvergleichsmethode (ein ComparatorObjekt) oder eine Objektvergleichsmethode (die ComparableSchnittstelle) bereitstellen.

    Schließlich bietet eine statische Klasse Collectionsnicht veränderbare (schreibgeschützte) und synchronisierte Versionen vorhandener Sammlungen. Die nicht modifizierbaren Klassen sind hilfreich, um unerwünschte Änderungen an einer Sammlung zu verhindern. Die synchronisierte Version einer Sammlung ist eine Notwendigkeit für Multithread-Programme.

Das Java Collections Framework ist Teil von Core Java und im java.util.collectionsPaket von JDK 1.2 enthalten. Das Framework ist auch als Paket für JDK 1.1 verfügbar (siehe Ressourcen).

Hinweis: Die JDK 1.1-Version von Sammlungen wird benannt com.sun.java.util.collections. Beachten Sie, dass mit der Version 1.1 entwickelter Code für die Version 1.2 aktualisiert und neu kompiliert werden muss und in 1.1 serialisierte Objekte nicht in 1.2 deserialisiert werden können.

Lassen Sie uns diese Vorteile nun genauer betrachten, indem Sie das Java Collections Framework mit einem eigenen Code ausführen.

Eine gute API

Der erste Vorteil des Java Collections Framework ist eine konsistente und regelmäßige API. Die API ist in einem Basissatz von Schnittstellen zu kodifizieren, Collection, Set, List, oder Map. Die CollectionSchnittstelle enthält grundlegende Erfassungsvorgänge wie Hinzufügen, Entfernen und Testen der Mitgliedschaft (Eindämmung). Jede Implementierung einer Sammlung, unabhängig davon, ob sie vom Java Collections Framework oder von einer Ihrer eigenen Kreationen bereitgestellt wird, unterstützt eine dieser Schnittstellen. Da das Collections-Framework regelmäßig und konsistent ist, lernen Sie einen großen Teil der Frameworks einfach durch Erlernen dieser Schnittstellen.

Beides Setund Listimplementieren die CollectionSchnittstelle. Die SetSchnittstelle ist Collectionbis auf eine zusätzliche Methode toArray, die a Setin ein ObjectArray konvertiert, identisch mit der Schnittstelle . Die ListSchnittstelle implementiert auch die CollectionSchnittstelle, bietet jedoch viele Accessoren, die einen ganzzahligen Index in der Liste verwenden. Zum Beispiel get, removeund setnehmen alle eine ganze Zahl, die das indizierte Element in der Liste betrifft. Die MapSchnittstelle ist nicht von der Sammlung abgeleitet, bietet jedoch eine Schnittstelle ähnlich den Methoden in java.util.Hashtable. Schlüssel werden verwendet, um Werte zu setzen und abzurufen. Jede dieser Schnittstellen wird in den folgenden Codebeispielen beschrieben.

Das folgende Codesegment zeigt, wie viele CollectionVorgänge für HashSeteine grundlegende Sammlung ausgeführt werden, die die SetSchnittstelle implementiert . A HashSetist einfach eine Menge, die keine doppelten Elemente zulässt und ihre Elemente nicht ordnet oder positioniert. Der Code zeigt, wie Sie eine grundlegende Sammlung erstellen und Elemente hinzufügen, entfernen und testen. Da Vectorjetzt die CollectionSchnittstelle unterstützt wird, können Sie diesen Code auch auf einem Vektor ausführen, den Sie testen können, indem Sie die HashSetDeklaration und den Konstruktor in a ändern Vector.

import java.util.collections. *; öffentliche Klasse CollectionTest {// Statik public static void main (String [] args) {System.out.println ("Sammlungstest"); // Eine Sammlung erstellen HashSet collection = new HashSet (); // Hinzufügen eines Strings dog1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; collection.add (dog1); collection.add (dog2); collection.add (dog3); // Größe von System.out.println ("Sammlung erstellt" + ", size =" + collection.size () + ", isEmpty =" + collection.isEmpty ()); // Containment System.out.println ("Sammlung enthält" + dog3 + ":" + collection.contains (dog3)); // Wiederholung. Iterator unterstützt hasNext. Entfernen Sie als Nächstes System.out.println ("Sammlungsiteration (unsortiert):"). Iterator iterator = collection.iterator (); while (Iterator.hasNext ()) System.out.println ("" + iterator.next ()); // Sammlung entfernen.remove (dog1); collection.clear (); }}

Let's now build on our basic knowledge of collections and look at other interfaces and implementations in the Java Collections Framework.

Good concrete implementations

We have exercised the Collection interface on a concrete collection, the HashSet. Let's now look at the complete set of concrete collection implementations provided in the Java Collections framework. (See the Resources section for a link to Sun's annotated outline of the Java Collections framework.)

Implementations
Hash Table Resizable Array Balanced Tree (Sorted) Linked List Legacy
Interfaces Set HashSet * TreeSet * *
List * ArrayList * LinkedList Vector
Map HashMap * TreeMap * Hashtable

Implementations marked with an asterix (*) make no sense or provide no compelling reason to implement. For instance, providing a List interface to a Hash Table makes no sense because there is no notion of order in a Hash Table. Similarly, there is no Map interface for a Linked List because a list has no notion of table lookup.

Let's now exercise the List interface by operating on concrete implementations that implement the List interface, the ArrayList, and the LinkedList. The code below is similar to the previous example, but it performs many List operations.

import java.util.collections.*; public class ListTest { // Statics public static void main( String [] args ) { System.out.println( "List Test" ); // Create a collection ArrayList list = new ArrayList(); // Adding String [] toys = { "Shoe", "Ball", "Frisbee" }; list.addAll( Arrays.toList( toys ) ); // Sizing System.out.println( "List created" + ", size=" + list.size() + ", isEmpty=" + list.isEmpty() ); // Iteration using indexes. System.out.println( "List iteration (unsorted):" ); for ( int i = 0; i < list.size(); i++ ) System.out.println( " " + list.get( i ) ); // Reverse Iteration using ListIterator System.out.println( "List iteration (reverse):" ); ListIterator iterator = list.listIterator( list.size() ); while ( iterator.hasPrevious() ) System.out.println( " " + iterator.previous() ); // Removing list.remove( 0 ); list.clear(); } } 

As with the first example, it's simple to swap out one implementation for another. You can use a LinkedList instead of an ArrayList simply by changing the line with the ArrayList constructor. Similarly, you can use a Vector, which now supports the List interface.

When deciding between these two implementations, you should consider whether the list is volatile (grows and shrinks often) and whether access is random or ordered. My own tests have shown that the ArrayList generally outperforms the LinkedList and the new Vector.

Notice how we add elements to the list: we use the addAll method and the static method Arrays.toList. This static method is one of the most useful utility methods in the Collections framework because it allows any array to be viewed as a List. Now an array may be used anywhere a Collection is needed.

Notice that I iterate through the list via an indexed accessor, get, and the ListIterator class. In addition to reverse iteration, the ListIterator class allows you to add, remove, and set any element in the list at the point addressed by the ListIterator. This approach is quite useful for filtering or updating a list on an element-by-element basis.

Die letzte grundlegende Schnittstelle im Java Collections Framework ist die Map. Diese Schnittstelle wird mit zwei neuen konkreten Implementierungen implementiert, der TreeMapund der HashMap. Dies TreeMapist eine ausgeglichene Baumimplementierung, die Elemente nach dem Schlüssel sortiert.

Lassen Sie uns die Verwendung der MapSchnittstelle anhand eines einfachen Beispiels veranschaulichen, das zeigt, wie eine Sammlung hinzugefügt, abgefragt und gelöscht wird. Dieses Beispiel, in dem die HashMapKlasse verwendet wird, unterscheidet sich nicht wesentlich von dem Beispiel Hashtablevor dem Debüt des Collections-Frameworks. Mit dem Update von Hashtablezur Unterstützung der MapSchnittstelle können Sie nun die Zeile, die das instanziiert, austauschen HashMapund durch eine Instanziierung des ersetzen Hashtable.