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 få
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
, ellerKort
- 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 implementererKollektion
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
ogVektor
, som er blevet opdateret til implementering afKollektion
grænseflader, nye indsamlingsimplementeringer er tilføjet, herunderHashSet
ogTreeSet
,ArrayList
ogLinkedList
ogHashMap
ogKort
. 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 typeOptælling
der tillader elementoperationer som indsættelse og sletning. DetIterator
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.eksVektor
returnere aListIterator
der tillader tovejs iteration og opdatering.Flere samlinger (
TreeSet
ogTreeMap
) 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 (aKomparator
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, få
, fjerne
og 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-bord | Resizable Array | Balanceret træ (sorteret) | Tilknyttet liste | Eftermæle | ||
Grænseflader | Sæt | HashSet | * | TreeSet | * | * |
Liste | * | ArrayList | * | LinkedList | Vektor | |
Kort | HashMap | * | 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, få
, 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
.