JDK 1.2 esittelee uuden objektikokoelmakehyksen, nimeltään Java Collections Framework. "Voi ei", huokaat, "ei toista sovellusliittymää, ei muuta opittavaa kehystä!" Mutta odota, ennen kuin käännyt pois, kuulkaa minut: Kokoelmat-kehys on vaivannäönne ja hyötyy ohjelmoinnistanne monin tavoin. Kolme suurta hyötyä tulee heti mieleen:
- Se lisää dramaattisesti kokoelmien luettavuutta tarjoamalla vakiosarjan liitäntöjä, joita monet ohjelmoijat voivat käyttää monissa sovelluksissa.
- Se tekee koodistasi joustavamman antamalla sinun siirtää ja palauttaa rajapintoja konkreettisten luokkien sijaan, yleistämällä koodisi sen sijaan, että lukitsisit sen.
- Se tarjoaa monia erityisiä käyttöliittymien toteutuksia, joiden avulla voit valita kokoelman, joka sopii parhaiten ja tarjoaa parhaan suorituskyvyn tarpeisiisi.
Ja se on vain aloittelijoille.
Kierros kehyksessä alkaa yleiskatsauksella eduista, joita se tarjoaa esineiden sarjaan tallennettaessa. Kuten pian huomaat, koska vanhat työhevosesi ystäväsi Hashtable
ja Vektori
tukea uutta sovellusliittymää, ohjelmat ovat yhtenäisiä ja ytimekkäitä - jotain sinä ja kehittäjät, jotka käyttävät koodiasi, varmasti huutavat.
Alustavan keskustelun jälkeen syvennämme yksityiskohtia.
Java-kokoelmien etu: Yleiskatsaus
Ennen kuin kokoelmat tekivät tervetulleimman debyyttinsä, tavalliset menetelmät Java-objektien ryhmittelemiseksi tapahtuivat taulukon kautta Vektori
, ja Hashtable
. Kaikilla näillä kolmella kokoelmalla on erilaiset menetelmät ja syntaksit jäsenten käyttämiseen: matriisit käyttävät hakasulkeita ([]), Vektori
käyttää elementAt
menetelmä ja Hashtable
käyttää saada
ja laittaa
menetelmiä. Nämä erot ovat johtaneet ohjelmoijat pitkään polulle epäjohdonmukaisuuteen omien kokoelmiensa toteuttamisessa - jotkut jäljittelevät Vektori
käyttömenetelmät ja jotkut jäljittelevät Luettelointi
käyttöliittymä.
Monimutkaisuuden lisäämiseksi suurin osa Vektori
menetelmät on merkitty lopullisiksi; eli et voi laajentaa Vektori
luokan vastaavanlaisen kokoelman toteuttamiseksi. Voisimme luoda kokoeluluokan, joka näytti a Vektori
ja toimi kuin a Vektori
, mutta sitä ei voitu siirtää menetelmälle, joka käyttää a Vektori
parametrina.
Lopuksi, mikään kokoelmista (taulukko, Vektori
tai Hashtable
) toteuttaa vakiojäsenen käyttöliittymän. Kun ohjelmoijat kehittivät algoritmeja (kuten lajikkeita) kokoelmien manipuloimiseksi, puhkesi lämmitetty keskustelu siitä, mikä objekti siirretään algoritmille. Jos ohitat matriisin tai a Vektori
? Pitäisikö sinun ottaa käyttöön molemmat käyttöliittymät? Keskustele päällekkäisyydestä ja sekaannuksesta.
Onneksi Java Collections Framework korjaa nämä ongelmat ja tarjoaa useita etuja verrattuna kehysten käyttämättä jättämiseen tai Vektori
ja Hashtable
:
Käytettävä joukko keräysrajapintoja
Toteuttamalla yksi perusrajapinnoista -
Kokoelma
,Aseta
,Lista
taiKartta
- varmistat, että luokkasi noudattaa yhteistä sovellusliittymää ja että siitä tulee säännöllisempi ja helposti ymmärrettävä. Joten riippumatta siitä, otatko käyttöön SQL-tietokannan, värimallien sovittimen tai etäkeskustelusovelluksen, jos otat käyttöönKokoelma
käyttöliittymässä, objektikokoelmasi toiminnot ovat käyttäjillesi hyvin tiedossa. Vakioliitännät myös yksinkertaistavat kokoelmien siirtämistä ja palauttamista luokkamenetelmiin ja palauttavat luokkamenetelmiin ja antavat menetelmien toimia laajemmalla valikoimalla kokoelmia.Perusjoukko keräystoteutuksia
Luotettavien lisäksi
Hashtable
jaVektori
, jotka on päivitettyKokoelma
käyttöliittymät, uusia kokoelmatoteutuksia on lisätty, mukaan lukienHashSet
jaPuujoukko
,ArrayList
jaLinkedList
jaHashMap
jaKartta
. Olemassa olevan, yleisen toteutuksen käyttäminen tekee koodistasi lyhyemmän ja nopeamman ladata. Olemassa olevan Java Java -koodin ytimen käyttäminen varmistaa myös, että kaikki peruskoodin parannukset parantavat myös koodisi suorituskykyä.Muita hyödyllisiä parannuksia
Jokainen kokoelma palauttaa nyt
Iteraattori
, parannettu tyyppiLuettelointi
joka sallii elementtitoiminnot, kuten lisäämisen ja poistamisen.Iteraattori
on "epäonnistunut nopeasti", mikä tarkoittaa, että saat poikkeuksen, jos toinen käyttäjä muuttaa toistamaasi luetteloa. Myös luettelopohjaiset kokoelmat, kutenVektori
palauta aListIterator
jotka mahdollistavat kaksisuuntaisen iteroinnin ja päivityksen.Useita kokoelmia (
Puujoukko
jaPuuKartta
) tukee implisiittisesti tilaamista. Käytä näitä luokkia ylläpitääksesi lajiteltu luettelo ilman vaivaa. Löydät pienimmät ja suurimmat elementit tai voit suorittaa binäärisen haun suurten luetteloiden suorituskyvyn parantamiseksi. Voit lajitella muita kokoelmia tarjoamalla kokoelmien vertailumenetelmän (aVertailija
objekti) tai objekti-vertailumenetelmä (Vertailukelpoinen
käyttöliittymä).Lopuksi staattinen luokka
Kokoelmat
tarjoaa muokattavia (vain luku) ja synkronoituja versioita olemassa olevista kokoelmista. Muokkaamattomat luokat auttavat estämään ei-toivotut muutokset kokoelmaan. Kokoelman synkronoitu versio on välttämätön monisäikeisille ohjelmille.
Java Collections Framework on osa Java-ydintä ja sisältyy java.util.collections
JDK 1.2 -paketti. Kehys on saatavana myös pakettina JDK 1.1: lle (katso Resurssit).
Huomaa: Kokoelmien JDK 1.1 -versio on nimetty com.sun.java.util.collections
. Muista, että 1.1-version kanssa kehitetty koodi on päivitettävä ja käännettävä uudelleen 1.2-versiolle, eikä mitään 1.1-sarjassa sarjoitettuja objekteja voida deserialisoida 1.2-versioon.
Tarkastellaan nyt tarkemmin näitä etuja käyttämällä Java Collections Framework -ohjelmaa jonkin oman koodin avulla.
Hyvä API
Java Collections Frameworkin ensimmäinen etu on johdonmukainen ja säännöllinen API. API on koodattu perusrajapinnoissa, Kokoelma
, Aseta
, Lista
tai Kartta
. Kokoelma
käyttöliittymä sisältää peruskäytön perustoiminnot, kuten jäsenyyden lisäämisen, poistamisen ja testit (suojauksen). Kokoelman toteuttaminen, riippumatta siitä, onko Java Collections Framework tai jokin oma luomuksesi, tukee yhtä näistä rajapinnoista. Koska Collections-kehys on säännöllinen ja johdonmukainen, opit suuren osan kehyksistä yksinkertaisesti oppimalla nämä rajapinnat.
Molemmat Aseta
ja Lista
toteuttaa Kokoelma
käyttöliittymä. Aseta
käyttöliittymä on identtinen Kokoelma
käyttöliittymä lukuun ottamatta lisämenetelmää, to Array
, joka muuntaa a Aseta
ja Esine
taulukko. Lista
käyttöliittymä toteuttaa myös Kokoelma
käyttöliittymä, mutta tarjoaa monia käyttöoikeuksia, jotka käyttävät luetteloon kokonaislukuindeksiä. Esimerkiksi, saada
, Poista
ja aseta
kaikki ottavat kokonaisluvun, joka vaikuttaa luettelon indeksoituun elementtiin. Kartta
käyttöliittymä ei ole peräisin kokoelmasta, mutta tarjoaa käyttöliittymän, joka on samanlainen kuin kohdassa java.util.Hashtable
. Avaimia käytetään arvojen asettamiseen ja saamiseen. Kukin näistä rajapinnoista on kuvattu seuraavissa koodiesimerkkeissä.
Seuraava koodisegmentti osoittaa kuinka suorittaa monia Kokoelma
toiminnot HashSet
, peruskokoelma, joka toteuttaa Aseta
käyttöliittymä. A HashSet
on yksinkertaisesti joukko, joka ei salli päällekkäisiä elementtejä eikä järjestä tai sijoita sen elementtejä. Koodi näyttää, miten luot peruskokoelman ja lisäät, poistat ja testaat elementtejä. Koska Vektori
tukee nyt Kokoelma
käyttöliittymässä, voit myös suorittaa tämän koodin vektorilla, jonka voit testata muuttamalla HashSet
vakuutus ja rakentaja a Vektori
.
tuo java.util.collections. *; public class CollectionTest {// Statics public static void main (String [] args) {System.out.println ("Kokoelmatesti"); // Luo kokoelma HashSet-kokoelma = new HashSet (); // Merkkijonon lisääminen1 = "Max", dog2 = "Bailey", dog3 = "Harriet"; collection.add (koira1); collection.add (koira2); collection.add (koira3); // Järjestelmän koko.out.println ("Kokoelma luotu" + ", size =" + collection.size () + ", isEmpty =" + collection.isEmpty ()); // Containing System.out.println ("Kokoelma sisältää" + dog3 + ":" + collection.contains (dog3)); // Iteraatio. Iterator tukee hasNext, seuraava, poista System.out.println ("Kokoelman iterointi (lajittelematon):"); Iteraattori iteraattori = collection.iterator (); while (iterator.hasNext ()) System.out.println ("" + iterator.next ()); // Poistetaan collection.remove (dog1); collection.clear (); }}
Rakennetaan nyt kokoelmien perustietämyksellemme ja tarkastellaan muita käyttöliittymiä ja toteutuksia Java Collections Frameworkissa.
Hyvät konkreettiset toteutukset
Olemme käyttäneet Kokoelma
käyttöliittymä konkreettiseen kokoelmaan, HashSet
. Tarkastellaan nyt kaikkia Java Collection -kehyksen sisältämiä konkreettisia kokoelmatoteutuksia. (Katso Resurssit-osiosta linkki Sunin Java-viitekehyksen huomautettuihin pääpiirteisiin.)
Toteutukset | ||||||
---|---|---|---|---|---|---|
Hash-taulukko | Muutettavissa oleva taulukko | Tasapainoinen puu (lajiteltu) | Linkitetty luettelo | Perintö | ||
Liitännät | Aseta | HashSet | * | Puujoukko | * | * |
Lista | * | ArrayList | * | LinkedList | Vektori | |
Kartta | HashMap | * | PuuKartta | * | Hashtable |
Asteriksilla (*) merkittyillä toteutuksilla ei ole mitään järkeä tai ne eivät tarjoa pakottavaa syytä toteuttaa. Esimerkiksi a Lista
käyttöliittymällä Hash-taulukkoon ei ole mitään järkeä, koska Hash-taulukossa ei ole järjestyskäsitystä. Samoin ei ole Kartta
käyttöliittymä linkitetylle luettelolle, koska luettelossa ei ole käsitettä taulukon hausta.
Harjoitellaan nyt Lista
käyttöliittymä toimimalla konkreettisissa toteutuksissa, jotka toteuttavat Lista
käyttöliittymä, ArrayList
, ja LinkedList
. Alla oleva koodi on samanlainen kuin edellinen esimerkki, mutta se suorittaa monia Lista
toimintaan.
tuo java.util.collections. *; public class ListTest {// Statics public static void main (String [] args) {System.out.println ("Luettelotesti"); // Luo kokoelma ArrayList list = new ArrayList (); // String [] -lelujen lisääminen = {"Kenkä", "Pallo", "Frisbee"}; list.addAll (Arrays.toList (lelut)); // Järjestelmän mitoitus.out.println ("Lista luotu" + ", size =" + list.size () + ", isEmpty =" + list.isEmpty ()); // Iteraatio indeksien avulla. System.out.println ("Lista iterointi (lajittelematon):"); for (int i = 0; i <list.size (); i ++) System.out.println ("" + list.get (i)); // Käänteinen iteraatio käyttäen ListIterator System.out.println ("Luettelon iterointi (käänteinen):"); ListIterator iterator = list.listIterator (list.size ()); while (iterator.hasPrevious ()) System.out.println ("" + iterator.previous ()); // Poistetaan list.remove (0); list.clear (); }}
Kuten ensimmäisessä esimerkissä, on helppo vaihtaa yksi toteutus toiseen. Voit käyttää a LinkedList
sijasta ArrayList
yksinkertaisesti muuttamalla viivaa ArrayList
rakentaja. Vastaavasti voit käyttää a Vektori
, joka tukee nyt Lista
käyttöliittymä.
Kun päätät näiden kahden toteutuksen välillä, sinun on harkittava, onko luettelo epävakaa (kasvaa ja kutistuu usein) ja onko pääsy satunnainen vai järjestetty. Omat testit ovat osoittaneet, että ArrayList
yleensä parempi kuin LinkedList
ja uusi Vektori
.
Huomaa, kuinka lisätään elementtejä luetteloon: käytämme addAll
menetelmä ja staattinen menetelmä Arrays.toList
. Tämä staattinen menetelmä on yksi hyödyllisimmistä hyödyllisyysmenetelmistä kokoelmakehyksessä, koska se sallii minkä tahansa taulukon tarkastelun a-muodossa Lista
. Nyt taulukkoa voidaan käyttää missä tahansa a Kokoelma
tarvitaan.
Huomaa, että iteroin luettelon läpi indeksoidun käyttöoikeuden kautta, saada
, ja ListIterator
luokassa. Käänteisen iteraation lisäksi ListIterator
luokan avulla voit lisätä, poistaa ja asettaa minkä tahansa elementin luettelosta pisteeseen, johon ListIterator
. Tämä lähestymistapa on varsin hyödyllinen suodatettaessa tai päivitettäessä luetteloa elementteittäin.
Viimeinen Java-käyttöjärjestelmän peruskäyttöliittymä on Kartta
. Tämä rajapinta toteutetaan kahdella uudella konkreettisella toteutuksella, PuuKartta
ja HashMap
. PuuKartta
on tasapainoinen puun toteutus, joka lajittelee elementit avaimen mukaan.
Valaistaan Kartta
käyttöliittymä yksinkertaisella esimerkillä, joka näyttää kuinka lisätä, kysellä ja tyhjentää kokoelma. Tässä esimerkissä käytetään HashMap
luokassa, ei ole paljon eroa siitä, miten käytimme Hashtable
ennen kokoelmakehyksen debyyttiä. Nyt päivitettäessä Hashtable
tukea Kartta
käyttöliittymässä, voit vaihtaa rivin, joka välittää HashMap
ja korvaa se Hashtable
.