Programmering

Kom godt i gang med Java Collections Framework

JDK 1.2 introducerer en ny ramme for objektsamlinger, kaldet Java Collections Framework. "Å nej," stønner du, "ikke en anden API, ikke en anden ramme at lære!" Men vent, inden du vender dig væk, skal du høre mig: Collections-rammen er din indsats værd og vil gavne din programmering på mange måder. Tre store fordele kommer straks i tankerne:

  • Det øger dramatisk læsbarheden af ​​dine samlinger ved at tilvejebringe et standardsæt af grænseflader, der skal bruges af mange programmører i mange applikationer.
  • Det gør din kode mere fleksibel ved at give dig mulighed for at videregive og returnere grænseflader i stedet for konkrete klasser, generalisere din kode i stedet for at låse den ned.
  • Det tilbyder mange specifikke implementeringer af grænsefladerne, så du kan vælge den samling, der passer bedst og tilbyder den højeste ydelse til dine behov.

Og det er bare for begyndere.

Vores rundvisning i rammen begynder med et overblik over fordelene ved lagring af objektsæt. Som du snart opdager, fordi dine gamle arbejdshestevenner Hashtable og Vektor understøtter den nye API, vil dine programmer være ensartede og koncise - noget du og udviklerne, der får adgang til din kode, vil helt sikkert juble for.

Efter vores indledende diskussion vil vi grave dybere ned i detaljerne.

Fordelen ved Java Collections: En oversigt

Før samlinger fik sin mest velkomne debut, var standardmetoderne til gruppering af Java-objekter via arrayet, the Vektor, og Hashtable. Alle tre af disse samlinger har forskellige metoder og syntaks for adgang til medlemmer: arrays bruger firkantede parentes ([]) symboler, Vektor bruger elementAt metode og Hashtable anvendelser og sætte metoder. Disse forskelle har længe ført programmører ned ad stien til inkonsistens i implementeringen af ​​deres egne samlinger - nogle efterligner Vektor adgangsmetoder og nogle efterligner Optælling interface.

For yderligere at komplicere tingene er det meste af Vektor metoder er markeret som endelige; det vil sige, du kan ikke udvide Vektor klasse til at implementere en lignende slags samling. Vi kunne oprette en samlingsklasse, der lignede en Vektor og handlede som en Vektor, men det kunne ikke overføres til en metode, der tager en Vektor som parameter.

Endelig er der ingen af ​​samlingerne (array, Vektor eller Hashtable) implementerer en standard medlemsadgangsgrænseflade. Da programmører udviklede algoritmer (som slags) til at manipulere samlinger, brød en opvarmet diskurs ud af, hvilket objekt der skulle overføres til algoritmen. Skal du passere en matrix eller en Vektor? Skal du implementere begge grænseflader? Tal om dobbeltarbejde og forvirring.

Heldigvis afhjælper Java Collections Framework disse problemer og tilbyder en række fordele i forhold til at bruge ingen rammer eller bruge Vektor og Hashtable:

  • Et brugbart sæt samlingsgrænseflader

    Ved at implementere en af ​​de grundlæggende grænseflader - Kollektion, Sæt, Liste, eller Kort - du sikrer, at din klasse overholder en fælles API og bliver mere regelmæssig og let forståelig. Så hvad enten du implementerer en SQL-database, en farveprøve-matcher eller en ekstern chatapplikation, hvis du implementerer Kollektion interface, er operationerne på din samling af objekter velkendte for dine brugere. Standardgrænsefladerne forenkler også overførsel og returnering af samlinger til og fra klassemetoder og gør det muligt for metoderne at arbejde på et bredere udvalg af samlinger.

  • Et grundlæggende sæt indsamlingsimplementeringer

    Ud over de pålidelige Hashtable og Vektor, som er blevet opdateret til implementering af Kollektion grænseflader, nye indsamlingsimplementeringer er tilføjet, herunder HashSet og TreeSet, ArrayList og LinkedListog HashMap og Kort. Brug af en eksisterende, fælles implementering gør din kode kortere og hurtigere at downloade. Brug af eksisterende Core Java-kodekerne sikrer også, at enhver forbedring af basiskoden også forbedrer ydeevnen for din kode.

  • Andre nyttige forbedringer

    Hver samling returnerer nu en Iterator, en forbedret type Optælling der tillader elementoperationer som indsættelse og sletning. Det Iterator er "fail-fast", hvilket betyder, at du får en undtagelse, hvis listen, du gentager, ændres af en anden bruger. Også listebaserede samlinger som f.eks Vektor returnere a ListIterator der tillader tovejs iteration og opdatering.

    Flere samlinger (TreeSet og TreeMap) understøtter implicit bestilling. Brug disse klasser til at opretholde en sorteret liste uden anstrengelse. Du kan finde de mindste og største elementer eller udføre en binær søgning for at forbedre ydelsen på store lister. Du kan sortere andre samlinger ved at angive en samling-sammenligningsmetode (a Komparator objekt) eller en objekt-sammenligningsmetode ( Sammenlignelig interface).

    Endelig en statisk klasse Samlinger leverer umodificerbare (skrivebeskyttede) og synkroniserede versioner af eksisterende samlinger. De umodificerbare klasser er nyttige til at forhindre uønskede ændringer i en samling. Den synkroniserede version af en samling er en nødvendighed for multitrådede programmer.

Java Collections Framework er en del af Core Java og er indeholdt i java.util.collections pakke med JDK 1.2. Rammen er også tilgængelig som en pakke til JDK 1.1 (se ressourcer).

Bemærk: JDK 1.1-versionen af ​​samlingerne er navngivet com.sun.java.util.collections. Husk, at kode, der er udviklet med 1.1-versionen, skal opdateres og kompileres til version 1.2, og alle objekter, der er serielt i 1.1, kan ikke deserialiseres til 1.2.

Lad os nu se nærmere på disse fordele ved at udøve Java Collections Framework med vores egen kode.

En god API

Den første fordel ved Java Collections Framework er en konsekvent og regelmæssig API. API'en er kodificeret i et grundlæggende sæt grænseflader, Kollektion, Sæt, Liste, eller Kort. Det Kollektion interface indeholder grundlæggende indsamlingshandlinger såsom tilføjelse, fjernelse og test for medlemskab (indeslutning). Enhver implementering af en samling, hvad enten den er leveret af Java Collections Framework eller en af ​​dine egne kreationer, understøtter en af ​​disse grænseflader. Fordi rammerne for samlinger er regelmæssige og konsekvente, lærer du en stor del af rammerne ved blot at lære disse grænseflader.

Begge Sæt og Liste implementere Kollektion interface. Det Sæt interface er identisk med Kollektion interface undtagen en ekstra metode, toArray, der konverterer en Sæt til en Objekt array. Det Liste interface implementerer også Kollektion interface, men giver mange accessorer, der bruger et heltal indeks på listen. For eksempel, , fjerneog sæt alle tager et heltal, der påvirker det indekserede element på listen. Det Kort interface stammer ikke fra indsamling, men giver en grænseflade svarende til metoderne i java.util.Hashtable. Nøgler bruges til at sætte og hente værdier. Hver af disse grænseflader er beskrevet i følgende kodeeksempler.

Følgende kodesegment demonstrerer, hvordan man udfører mange Kollektion operationer på HashSet, en grundlæggende samling, der implementerer Sæt interface. EN HashSet er simpelthen et sæt, der ikke tillader duplikatelementer og ikke bestiller eller placerer dets elementer. Koden viser, hvordan du opretter en grundlæggende samling og tilføjer, fjerner og tester for elementer. Fordi Vektor understøtter nu Kollektion interface, kan du også udføre denne kode på en vektor, som du kan teste ved at ændre HashSet erklæring og konstruktør til en Vektor.

import java.util.collections. *; public class CollectionTest {// Statics public static void main (String [] args) {System.out.println ("Collection Test"); // Opret en samling HashSet-samling = ny HashSet (); // Tilføjelse af streng hund1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; collection.add (hund1); collection.add (dog2); collection.add (dog3); // Størrelse System.out.println ("Samling oprettet" + ", størrelse =" + samling.størrelse () + ", isEmpty =" + samling.isEmpty ()); // Containment System.out.println ("Samlingen indeholder" + dog3 + ":" + collection.contains (dog3)); // Iteration. Iterator understøtter hasNext, fjern derefter System.out.println ("Samling iteration (usorteret):"); Iterator iterator = collection.iterator (); mens (iterator.hasNext ()) System.out.println ("" + iterator.next ()); // Fjernelse af collection.remove (dog1); collection.clear (); }} 

Lad os nu bygge videre på vores grundlæggende viden om samlinger og se på andre grænseflader og implementeringer i Java Collections Framework.

Gode ​​konkrete implementeringer

Vi har udøvet Kollektion interface på en konkret samling, HashSet. Lad os nu se på det komplette sæt konkrete indsamlingsimplementeringer, der leveres i Java Collections-rammen. (Se afsnittet Ressourcer for et link til Suns kommenterede oversigt over Java Collections-rammen.)

Implementeringer
Hash-bordResizable ArrayBalanceret træ (sorteret)Tilknyttet listeEftermæle
Grænseflader SætHashSet* TreeSet* *
Liste* ArrayList* LinkedListVektor
KortHashMap* TreeMap* Hashtable

Implementeringer markeret med en asterix (*) giver ingen mening eller giver ingen tvingende grund til at implementere. For eksempel at levere en Liste interface til en Hash-tabel giver ingen mening, fordi der ikke er nogen forestilling om orden i en Hash-tabel. Tilsvarende er der ingen Kort interface til en sammenkædet liste, fordi en liste ikke har nogen opfattelse af tabelopslag.

Lad os nu udøve Liste interface ved at arbejde på konkrete implementeringer, der implementerer Liste interface, den ArrayList, og LinkedList. Koden nedenfor svarer til det foregående eksempel, men den udfører mange Liste operationer.

import java.util.collections. *; public class ListTest {// Statics public static void main (String [] args) {System.out.println ("List Test"); // Opret en samling ArrayList-liste = ny ArrayList (); // Tilføjelse af streng [] legetøj = {"Sko", "Ball", "Frisbee"}; list.addAll (Arrays.toList (legetøj)); // Størrelse System.out.println ("Liste oprettet" + ", størrelse =" + liste.størrelse () + ", isEmpty =" + liste.isEmpty ()); // Iteration ved hjælp af indekser. System.out.println ("Liste iteration (usorteret):"); for (int i = 0; i <list.size (); i ++) System.out.println ("" + list.get (i)); // Reverse Iteration ved hjælp af ListIterator System.out.println ("List iteration (reverse):"); ListIterator iterator = list.listIterator (list.size ()); mens (iterator.hasPrevious ()) System.out.println ("" + iterator.previous ()); // Fjernelse af listen. Fjern (0); list.clear (); }} 

Som med det første eksempel er det nemt at bytte en implementering til en anden. Du kan bruge en LinkedList i stedet for en ArrayList blot ved at ændre linjen med ArrayList konstruktør. På samme måde kan du bruge en Vektor, som nu understøtter Liste interface.

Når du beslutter mellem disse to implementeringer, skal du overveje, om listen er ustabil (vokser og krymper ofte), og om adgangen er tilfældig eller ordnet. Mine egne tests har vist, at ArrayList generelt bedre end LinkedList og det nye Vektor.

Læg mærke til, hvordan vi tilføjer elementer til listen: vi bruger tilføjAlle metode og den statiske metode Arrays.toList. Denne statiske metode er en af ​​de mest nyttige hjælpemetoder i rammerne for samlinger, fordi den gør det muligt at se ethvert array som en Liste. Nu kan en matrix bruges hvor som helst a Kollektion er nødvendig.

Bemærk, at jeg gentager listen via en indekseret accessor, , og ListIterator klasse. Ud over at vende iteration, er ListIterator klasse giver dig mulighed for at tilføje, fjerne og indstille ethvert element på listen på det sted, adresseret af ListIterator. Denne tilgang er ret nyttig til filtrering eller opdatering af en liste på element-for-element-basis.

Den sidste grundlæggende grænseflade i Java Collections Framework er Kort. Denne grænseflade er implementeret med to nye konkrete implementeringer, TreeMap og HashMap. Det TreeMap er en afbalanceret træimplementering, der sorterer elementer efter nøglen.

Lad os illustrere brugen af Kort interface med et simpelt eksempel, der viser, hvordan du tilføjer, spørger og rydder en samling. Dette eksempel, der bruger HashMap klasse, er ikke meget forskellig fra, hvordan vi brugte Hashtable forud for debut af Collections-rammen. Nu med opdateringen af Hashtable at støtte Kort interface, kan du bytte den linje, der instantierer HashMap og udskift det med en instantiering af Hashtable.