Kurt Nørmark ©
Department of Computer Science, Aalborg University, Denmark
September 2001
Abstract Previous lecture Next lecture Index References Contents | Vi har tidligere set på de basale datastrukturer arrays og lister, endog i en objekt-orienterede udgaver.
I denne lektion starter vi med at se på en generalisering af arrays og lister, som kaldes Collections.
Dette emne falder helt naturligt i forlængelse af forrige lektion om klassedesign. Senere i lektionen studerer vi Java's hierarki af stream klasser. |
Collections |
Introduktion til collections Slide Note Contents Index References Speak |
|
Exercise 11.1. Klassen Kortbunke | I forlængelse af opgaven om Spillekort fra en tidligere lektion vil vi i denne opgave
programmere en klasse Kortbunke, som repræsenterer en bunke
af kort. En instans af denne klasse kan bruges til at repræsentere
et komplet spil kort ligesom den kan bruges til at repræsentere
de kort, en spiller har på hånden. Ideen med opgaven er at benytte en Java Collection klasse som grundlaget for implementationen. Overvej hvilken, og overvej om en Kortbunke skal udvide/specialisere en Collection klasse, være klient af en Collection klasse, eller blot implementere et Collection interface. Vi ønsker at at kunne repræsentere en bestemt ordning mellem kortene, således at vi f.eks. kan tale om det øverste kort og det nederste kort. Følgende operationer skal være mulige på instanser af Kortbunke (hverken flere eller færre):
Datarepræsentationen skal være privat i klassen. Det vil være hensigtsmæssigt at have følgende udvalg af konstruktorer:
Overvej hvorledes du ønsker at skelne mellem disse tre konstruktorer parametermæssigt. |
Exercise 11.2. Krig - et simpelt kortspil | I forlængelse af opgaven om Spillekort og opgaven om Kortbunke vil vi i denne opgave
programmere en applikation, som anvender et spil kort til at gennemføre et kortspil, som mange børn kalder 'Krig' Spillet spilles af to spillere. I denne opgave spiller Computeren begge spillere. Der er altså tale om ultimativ effektivisering, idet vi nu kan spille Krig på under et sekund... Kortene deles ligeligt mellem to spillere. Hver spiller har en bunke kort foran sig. Spillet går ud på at erobre alle modspillerens kort. Spillet forløber således: Hver spiller tager det øverste kort. Den spiller, som har det største kort vinder begge kort. Vinderen lægger de vundne kort i bunden af sin bunke. Hvis to kort er af samme størrelse er der 'krig'. Hver spiller putter de to ens kort i en pulje, som forstørres med yderligere to kort fra hver spiller (øverst fra bunken). Dernæst sammenlignes de øverste kort fra de to resterende bunker igen, og den spiller der har det største vinder hele puljen. Er der igen lighed gentages krigen, med det resultat at puljen bliver større og større. Den spiller der først mister alle sine kort taber spillet. Skriv programmet således at der bliver udskrevet et spor af spillet, der fortæller om hver duel og hver krig. Det er en fordel at man løbende kan se hvor mange kort hver spiller har tilbage. |
|
Collection interfaces Slide Note Contents Index References Speak | Vi starter med et overblik over hierarkierne af Collection interfaces i Java |
|
Figure. De to bidrag til Collection hierarkierne i Java. | ![]() |
|
|
Interfacet Collection Slide Note Contents Index References Speak | Vi starter med at studere det mest generelle interface i collection hierarkiet. Dette kaldes helt naturligt Collection |
|
|
|
Interfacet Set Slide Note Contents Index References Speak | Vi fortsætter med at studere interfacet Set, som repræsenterer mængder. |
|
Set interfacet er stort set indentisk med Collection interfacet. Der er dog nogle stærkere krav til nogle af operationerne, eksempelvis kravet om at et element højst kan være repræsenteret én gang i et Set objekt. Vi kan sige, at invarianten af en klasser, som implementerer Set interfacet, er strammet. Bemærk, at interfaces ikke specificerer konstruktorer. Angående equal i Set og Collection: I Collections kan equal implementeres som Object equal, altså som ==. I Set har equal en mere element-orienteret betydning. To ikke-identiske mængde objekter set1 og set2 kan altså godt foranledige set1.equal(set2) |
|
Klassiske mængedeoperationer Slide Note Contents Index References Speak | Vi ser her på, hvordan man kan realisere nogle af de klassiske mængde operationer ved brug af operationerne i interfacet Set |
|
Operationerne addAll, retainAll og removeAll ændrer på modtager objektets indhold. Vi kan sige, at resultatet af operationen overskriver s1 i eksemplerne. Dette er nok ikke altid det vi ønsker. Hvis ikke, skal vi sørge for at kopiere s1 inden vi kalder mængde operationen:
|
|
Klasserne HashSet og TreeSet Slide Note Contents Index References Speak | Vi ser nu på konkrete klasser i Java biblioteket, som implementerer interfacet Set. |
TreeSet implementer faktisk et subinterface af Set, nemlig SortedSet. SortedSet kræver at elementerne i mængden implementerer Comparable grænsefladen. Vi ser på Comparable, element ordning og sortering senere i denne lektion. Bemærk at Comparable, som omtalt her, ikke er det samme som den abstrakte klasse Comparable, vi diskuterede i lektionen om klassedesign. Ordningerne, som der er tale om, kommer til udtryk når vi returnerer en iterator på mængden via operationen iterator(). |
Når vi skriver, at HashSet operationerne har forventet konstant tidskompleksitet, betyder det, at vi ikke kan garantere konstante køretider i worstcase. Den faktiske tidskompleksitet afhænger bl.a. af hashtabellens opfyldningsgrad. |
|
Et eksempel på anvendelse af Set Slide Note Contents Index References Speak | Vi ser nu på en konkret og realistisk anvendelse af Set interfacet. |
Program: Et eksempel på en anvendelse af en Set klasse.
Via argumentet til metoden main angiver vi en række tekststrenge, som indsættes
i en mængde m. Hvis en allerede indsat streng indsættes igen registreres dette
ved at add returnerer værdien false. Derved udskriver programmet en besked om, at
der er opdaget en duplikat. Programmet afsluttes med at udskrive antallet for forskellige
ord, samt selve mængden. Bemærk hvor hensigtsmæssigt det er, at Set klasser redefinerer
metoden toString(). Dette program er taget direkte fra The Java Tutorial.
|
|
|
Interfacet List Slide Note Contents Index References Speak | Vi går nu over til at se på List interfacet |
|
|
|
Interfacet List Slide Note Contents Index References Speak | Vi fortsætter diskussionen af List fra forrige side |
|
List i forhold til klassen Vector Slide Note Contents Index References Speak | Vi har tidligere i en tidligere lektion set på Vector klassen. Vi vil her relatere denne klasse til interfacet List. |
|
|
|
|
Klasserne ArrayList og LinkedList Slide Note Contents Index References Speak |
|
|
Et eksempel på anvendelse af List Slide Note Contents Index References Speak | Vi ser nu på en konkret og realistisk anvendelse af List interfacet. |
Program: Et eksempel på en anvendelse af ArrayList.
Eksemplet svare nøje til et eksempel vi tidligere har set under gennemgangen af
klassen Vector i lektionen om arrays og lister.
|
|
|
Interfacet Map Slide Note Contents Index References Speak |
|
|
|
Klasserne HashMap og TreeMap Slide Note Contents Index References Speak |
|
|
|
Et eksempel på anvendelse af Map Slide Note Contents Index References Speak |
Program: Et eksempel på anvendelse af Map.
Via argument array'et til main metoden overfører vi en række tesktstrenge.
Disse tekststrenge organiseres i en Map, som afbilder tekststrengen til det hidtil sete
antal forekomster. Bemærk, at værdien i et (nøgle,værdi)-par skal være et objekt; vi kan altså
ikke afbilde en streng til et heltal. Derfor wrappes heltal af typen int til typen Integer.
Eksemplet er taget fra afsnittet 'The Map Interface' i Java Tutorial. Jeg har omskrevet det en smule,
for at gøre det lidt mere klart, hvad der foregår.
|
|
|
Iterators for collections Slide Note Contents Index References Speak | Ligesom Enumerations spiller en vigtig rolle som iterators for kædede lister mv. er iterators særdeles vigtige i forbindelse med Java collections. Vi ser her på iterator begrebet, som det er knyttet til collections. Som vi vil se, er begrebet udvidet lidt i forhold til enumeration. |
|
|
|
Syn på collections Slide Note Contents Index References Speak | I en del forskellige sammenhænge kan der laves syn (views) på Collection og Map objekter, som gør det muligt at manipulere underliggende collections gennem et collection objekt, der opfattes som et syn. |
|
|
Hvad med søgning og sortering? Slide Note Contents Index References Speak |
Vi stiller her et spørgsmål, som bliver besvaret på de følgende sider. |
|
Samlinger af statiske metoder Slide Note Contents Index References Speak | Vi slutter denne afdeling med at se på to klasser, som udelukkende indeholder statiske metoder. Metoderne i Collections klassen arbejder på Collection objekter af forskellige typer. Metoderne i Arrays klassen arbejder på 'native' Java arrays. Bemærk flertals betegnelsen af disse klasser. Der er altså stor forskel på 'Collection' interfacet og Collections klassen. |
|
|
|
|
Algoritmer tilknyttet Collections |
Overblik over Collection algoritmer Slide Note Contents Index References Speak | Vi starter med at give et overblik over de algoritmer, som er knyttet til Collection klasserne |
|
|
|
Ordninger på Collections Slide Note Contents Index References Speak |
|
|
|
Detaljer om sammenligning af objekter Slide Note Contents Index References Speak |
|
Program: Et eksempel på definition af en naturlig ordning i en klasse Name.
Eksemplet er lånt stort set uændret fra The Java Tutorial.
|
|
Program: En anvendelse af klassen Name.
Denne klasse er ligeledes lånt fra The Java Tutorial.
|
|
Stream klassehierarkierne |
Stream begrebet Slide Note Contents Index References Speak |
The concept stream: En stream er en mængde af information, der bringes til eller fra et program, og som processeres sekventielt | En stream er en sekventielt ordnet mængde af information. Informationen skrives af et program til et 'bestemt sted'. Eller informationen læses af et program fra et 'bestemt sted'. Det omtalte sted er ofte en fil, men det kan også være andet, såsom en netværksforbindelse eller et andet program |
|
|
Streams i Java Slide Note Contents Index References Speak |
|
|
|
Reader og Writer hierarkierne Slide Note Contents Index References Speak | Her viser vi hierarkierne af Reader og Writer klasserne, som alle arbejder på tegn |
Figure. Reader og Writer hierarkierne. Kursiverede klassenavne repræsenterer abstrakte klasser | ![]() |
Kategorisering af tegn streams Slide Note Contents Index References Speak |
De strømme, som ikke læser eller skriver fra/til 'sinks' kaldes 'processing streams'; sådanne streams behandler data i forbifarten. |
Tegn streams Slide Note Contents Index References Speak | Vi ser her nærmere på Reader og Writer, altså streams af tegn |
|
|
|
Eksempel på anvendelse af klasserne FileReader og FileWriter Slide Note Contents Index References Speak | Vi ser her på et eksempel på anvendelser af klasserne FileReader og FileWriter. Eksemplet er tilpasset fra The Java Tutorial |
Program: Et eksempel hvor tegnene fra én tekstfil kopieres over på en anden.
Navnenen på filen tages fra parameteren til main (en array af String).
Hvis man kører programmet med 'java copy xxx yyy' kopieres filen
xxx til filen yyy.
|
|
|
InputStream og OutputStream hierarkierne Slide Note Contents Index References Speak | Her viser vi hierarkierne af Inputstream og Outputstream klasserne, som arbejder på 'rå' bytes, altså binære filer |
Figure. InputStream og OutputStream hierarkierne. Kursiverede klassenavne repræsenterer også her abstrakte klasser | ![]() |
Kategorisering af byte streams Slide Note Contents Index References Speak |
|
|
|
Byte streams Slide Note Contents Index References Speak | Vi ser her nærmere på InputStream og OutputStream, altså streams af bytes |
|
Stream filtre Slide Note Contents Index References Speak | Det er muligt i Java at sammensætte filter streams på mangfoldige måder. Vi ser her på et par eksempler |
|
En binær fil hvorfra der læses primitive Java data gennem en buffer: |
Program: Et program der viser hvordan streams kan kombineres.
Variablen din refererer til en stream som er bygget fra filen 'number.dat'. På denne fil
laves en FileInputStream, som kan læse binære data. På denne laves en BufferedInputStream, som
læser disse data gennem en buffer. Endelig konstrueres en DataInputStream, som tillader os at
læse de primitive Java data gennem bufferen |
|
Program: Et program som skriver et tal og en boolean på en binær fil.
|
|
|
Chapter 11: Collections og streams
Course home Author home About producing this web Previous lecture (top) Next lecture (top) Previous lecture (bund) Next lecture (bund)
Generated: March 31, 2008, 12:09:19