Započnite s Java Collections Frameworkom

JDK 1.2 predstavlja novi okvir za zbirke objekata, nazvan Java Collections Framework. "Ma ne", zastenješ, "ni drugi API, ni drugi okvir za učenje!" Ali pričekajte, prije nego što se okrenete, poslušajte me: okvir Zbirke vrijedan je vašeg truda i na mnogo će načina koristiti vašem programiranju. Tri velike prednosti odmah mi padaju na pamet:

  • Dramatično povećava čitljivost vaših zbirki pružajući standardni set sučelja koji mnogi programeri koriste u mnogim aplikacijama.
  • Čini vaš kod fleksibilnijim omogućujući vam da prosljeđujete i vraćate sučelja umjesto konkretnih klasa, generalizirajući vaš kod umjesto da ga zaključavate.
  • Nudi mnoštvo specifičnih implementacija sučelja, što vam omogućuje odabir kolekcije koja najviše odgovara i nudi najviše performanse za vaše potrebe.

I to samo za početak.

Naš obilazak okvira započet će pregledom prednosti koje pruža pohrana skupova predmeta. Kao što ćete uskoro otkriti, jer će vaši stari prijatelji s radnog konja Hashtablei Vectorpodržavati novi API, vaši će programi biti ujednačeni i sažeti - što ćete zasigurno razveseliti vi i programeri koji pristupaju vašem kodu.

Nakon naše preliminarne rasprave, dublje ćemo istražiti detalje.

Prednost Java zbirki: Pregled

Prije nego što su Zbirke debitirale vrlo dobrodošlo, standardne metode grupiranja Java objekata bile su putem polja, the Vectori Hashtable. Sve tri ove zbirke imaju različite metode i sintaksu za pristup članovima: nizovi koriste simbole uglastih zagrada ([]), Vectorkoriste elementAtmetodu i Hashtableupotrebe geti putmetode. Te razlike već dugo vode programera na put prema nedosljednosti u implementaciji vlastitih kolekcija - neke oponašaju Vectormetode pristupa, a neke oponašaju Enumerationsučelje.

Da bi se stvari dodatno zakomplicirale, većina Vectormetoda označena je kao konačna; to jest, ne možete proširiti Vectorklasu kako biste implementirali sličnu vrstu kolekcije. Mogli bismo stvoriti klasu kolekcije koja je izgledala poput a Vectori ponašala se kao a Vector, ali nije se mogla proslijediti metodi koja Vectorkao parametar uzima a .

Konačno, niti jedna kolekcija (polje Vectorili Hashtable) ne implementira standardno sučelje za pristup članovima. Kako su programeri razvijali algoritme (poput sortiranja) za manipuliranje zbirkama, izbio je žestok diskurs o tome koji će objekt proslijediti algoritmu. Trebate li proći niz ili a Vector? Trebate li implementirati oba sučelja? Razgovarajte o dupliciranju i zabuni.

Srećom, Java Collections Framework rješava ove probleme i nudi brojne prednosti u odnosu na upotrebu nikakvog okvira ili korištenje Vectori Hashtable:

  • Korisni skup sučelja za prikupljanje

    Implementacijom jednog od osnovnih sučelja - Collection, Set, Listili Map- što bi se osiguralo svoje klase u skladu sa zajedničkim API i postaje redoviti i lako razumjeti. Dakle, bez obzira implementirate li SQL bazu podataka, podudaranje uzorka boja ili aplikaciju za udaljeni chat, ako implementirate Collectionsučelje, operacije na vašoj zbirci objekata dobro su poznate vašim korisnicima. Standardna sučelja također pojednostavljuju prosljeđivanje i vraćanje zbirki u metode klasa i iz njih i omogućuju rad metoda na širokom spektru zbirki.

  • Osnovni skup implementacija kolekcije

    Pored pouzdanih Hashtablei Vector, koji su ažurirani radi implementacije Collectionsučelja, dodane su nove implementacije kolekcije, uključujući HashSeti TreeSet, ArrayListi LinkedList, i HashMapi Map. Korištenje postojeće, uobičajene implementacije čini vaš kod kraćim i bržim za preuzimanje. Također, upotreba postojeće jezgre Core Java koda osigurava da će sva poboljšanja osnovnog koda poboljšati i izvedbu vašeg koda.

  • Ostala korisna poboljšanja

    Svaka zbirka sada vraća Iterator, poboljšanu vrstu Enumerationkoja omogućuje operacije elemenata poput umetanja i brisanja. Značajka Iteratorje "neuspješna", što znači da dobivate iznimku ako drugi korisnik promijeni popis koji ponavljate. Također, zbirke zasnovane na popisu, poput Vectorreturn a, ListIteratoromogućuju dvosmjernu iteraciju i ažuriranje.

    Nekoliko zbirki ( TreeSeti TreeMap) implicitno podržava naručivanje. Koristite ove klase za održavanje razvrstanog popisa bez napora. Možete pronaći najmanji i najveći element ili izvršiti binarno pretraživanje kako biste poboljšali izvedbu velikih popisa. Ostale zbirke možete sortirati pružajući metodu uspoređivanja zbirki ( Comparatorobjekt) ili metodu usporedbe objekata ( Comparablesučelje).

    Napokon, statička klasa Collectionspruža nepromjenjive (samo za čitanje) i sinkronizirane verzije postojećih kolekcija. Neizmjenjivi razredi korisni su za sprečavanje neželjenih promjena u zbirci. Sinkronizirana verzija zbirke nužna je za višenitne programe.

Okvir Java Collections dio je Core Java i sadržan je u java.util.collectionspaketu JDK 1.2. Okvir je također dostupan kao paket za JDK 1.1 (vidi Resursi).

Napomena: Nazvana je verzija zbirki JDK 1.1 com.sun.java.util.collections. Imajte na umu da se kod razvijen s verzijom 1.1 mora ažurirati i prekompajlirati za verziju 1.2, a objekti serializirani u 1.1 ne mogu se deserijalizirati u 1.2.

Pogledajmo sada bliže ove prednosti primjenjujući Java Collections Framework s nekim vlastitim kodom.

Dobar API

Prva prednost Okvira Java Collections je dosljedan i redovit API. API je kodificirana u osnovni skup sučelja, Collection, Set, List, ili Map. CollectionSučelje sadrži osnovne djelatnosti skupljanja kao što su dodavanje, uklanjanje i testova za članstvo (zatvorenost). Svaka implementacija kolekcije, bilo da je ona predviđena Java Collections Framework ili nekom od vaših vlastitih kreacija, podržavat će jedno od ovih sučelja. Budući da je okvir Zbirke redovan i dosljedan, naučit ćete velik dio okvira jednostavnim učenjem ovih sučelja.

Oba Seti Listimplementirati Collectionsučelje. SetSučelje je identičan Collectionsučelja osim za dodatni postupak, toArraykoji pretvara Sets Objectpolja. ListSučelje također implementira Collectionsučelje, ali pruža mnoge Pristupnici koji koriste indeks cijeli broj u popisu. Na primjer, get, removei setsve uzeti jedan cijeli broj koji utječe na indeks elementa u popisu. MapSučelje ne proizlazi iz kolekcije, ali pruža sučelje slično metodama u java.util.Hashtable. Tipke se koriste za stavljanje i dobivanje vrijednosti. Svako od ovih sučelja opisano je u sljedećim primjerima koda.

Sljedeći segment koda pokazuje kako izvesti mnoge Collectionoperacije na HashSet, osnovnoj zbirci koja implementira Setsučelje. A HashSetje jednostavno skup koji ne dopušta dvostruke elemente i ne raspoređuje niti postavlja svoje elemente. Kôd pokazuje kako stvarate osnovnu zbirku i dodajete, uklanjate i testirate elemente. Budući da Vectorsada podržava Collectionsučelje, ovaj kod možete izvršiti i na vektoru koji možete testirati promjenom HashSetdeklaracije i konstruktora u Vector.

import java.util.collections. *; javna klasa CollectionTest {// Statika javna statička void glavna (String [] args) {System.out.println ("Test kolekcije"); // Stvaranje kolekcije HashSet kolekcije = novi HashSet (); // Dodavanje niza dog1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; collection.add (pas1); collection.add (pas2); collection.add (pas3); // Veličina sustava System.out.println ("Zbirka stvorena" + ", size =" + collection.size () + ", isEmpty =" + collection.isEmpty ()); // Containment System.out.println ("Zbirka sadrži" + dog3 + ":" + collection.contens (dog3)); // Ponavljanje. Iterator podržava hasNext, zatim uklonite System.out.println ("Iteracija kolekcije (nesortirano):"); Iterator iterator = collection.iterator (); while (iterator.hasNext ()) System.out.println ("" + iterator.next ()); // Uklanjanje collection.remove (dog1); collection.clear (); }}

Nadamo se sada na našem osnovnom znanju o zbirkama i pogledajmo druga sučelja i implementacije u okviru Java Collections Framework.

Dobre konkretne implementacije

Mi smo ostvario Collectionsučelje na zbirci betona, HashSet. Pogledajmo sada kompletan set implementacija konkretne kolekcije koji se pružaju u okviru Java Collections. (Pogledajte odjeljak Resursi kako biste pronašli vezu do Sunčevog naznačenog obrisa okvira Java Collections.)

Provedbe
Hash tablica Spremivi niz Uravnoteženo stablo (poredano) Povezani popis Ostavština
Sučelja Postavi HashSet * TreeSet * *
Popis * ArrayList * LinkedList Vektor
Karta 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.

Posljednje osnovno sučelje u okviru Java Collections Framework je Map. Ovo sučelje implementirano je s dvije nove konkretne implementacije, TreeMapi HashMap. To TreeMapje uravnotežena implementacija stabla koja razvrstava elemente po ključu.

Ilustrirajmo upotrebu Mapsučelja jednostavnim primjerom koji pokazuje kako dodati, upitati i očistiti zbirku. Ovaj se primjer, koji koristi HashMapklasu, ne razlikuje mnogo od onoga kako smo koristili Hashtableprije debija okvira Collections. Sada, s ažuriranjem Hashtableza podršku Mapsučelja, možete zamijeniti redak koji instancira HashMapi zamijeniti ga instancijom datoteke Hashtable.