Προγραµµατισµός ΙΙ Ηγλώσσααντικειµενοστραφούς προγραµµατισµού Java ιδάσκων ηµήτριος Κατσαρός, Ph.D. @ Τµ. Μηχανικών Η/Υ, Τηλεπικοινωνιών & ικτύων Πανεπιστήµιο Θεσσαλίας ιάλεξη 14η: 31/08/2006 1
Συλλογές και Επαναλήπτες Collections and Iterators 2
Συλλογές - Collections Μια συλλογή (collection) της Java είναι οποιαδήποτε κλάση κρατά (αποθηκεύει) αντικείµενα καιυλοποιείτοcollection interface Για παράδειγµα, η κλάσηarraylist<t> είναι µια Java collection κλάση, και υλοποιεί όλες τις µεθόδους του Collection interface Οι collections χρησιµοποιούνται σε συνδυασµό µε τους iterators Το Collection interface είναι το υψηλότερο επίπεδο του πλαισίου της Java για τις collection κλάσεις Όλες οι collection κλάσεις που θα παρουσιάσουµε βρίσκονται στο java.util 3
Το Collection Landscape 4
Wildcards Οι κλάσεις και τα interfaces στο πλαίσιο του collection µπορούν να έχουν µια προσδιοριστές για παράµετρο τύπου που δεν καθορίζουν πλήρως τον τύπο δεδοµένων που θα ενσωµατωθεί αντί της παραµέτρου τύπου Επειδή καθορίζουν µια µεγάλη γκάµα πιθανών τύπων, είναι γνωστοί ως wildcards public void method(string arg1, ArrayList<?> arg2) Στο παραπάνω παράδειγµα, το πρώτο όρισµα είναι τύπου String, ενώ το δεύτερο όρισµα µπορεί να είναι ένα ArrayList<T> µε οποιοδήποτεβασικό τύπο 5
Wildcards Ένα όριο µπορεί να τοποθετηθεί σε έναν wildcard, καθορίζοντας ότι ο τύπος πρέπει να είναι πρόγονος ή απόγονος κάποιας κλάσης ή κάποιου interface Οσυµβολισµός <? extends String> καθορίζει ότι το όρισµα πουθαενσωµατωθεί θα είναι αντικείµενο οποιασδήποτε κλάσης είναι απόγονος της κλάσης String Οσυµβολισµός <? super String> καθορίζει ότι το όρισµα που θα ενσωµατωθεί θα είναι αντικείµενο οποιασδήποτε κλάσης είναι πρόγονος της κλάσης String 6
Το πλαίσιο (framework) Collection Το Collection<T> interface περιγράφει τις βασικές λειτουργίες που θα πρέπει να υλοποιούν όλες οι collection κλάσεις Οι κεφαλίδες των µεθόδων για τις λειτουργίες αυτές δείχνονται στις επόµενες διαφάνειες Αφού ένα interface είναι ένας τύπος, µπορεί να οριστεί οποιαδήποτε µέθοδος µε παράµετρο του τύπου Collection<T> Σε αυτή την παράµετρο µπορεί να ενσωµατωθεί ένα όρισµα που είναι αντικείµενο οποιασδήποτε κλάσης στο πλαίσιο collection 7
Κεφαλίδες µεθόδων στο Collection<T> Interface (1/10) 8
Κεφαλίδες µεθόδων στο Collection<T> Interface (2/10) 9
Κεφαλίδες µεθόδων στο Collection<T> Interface (3/10) 10
Κεφαλίδες µεθόδων στο Collection<T> Interface (4/10) 11
Κεφαλίδες µεθόδων στο Collection<T> Interface (5/10) 12
Κεφαλίδες µεθόδων στο Collection<T> Interface (6/10) 13
Κεφαλίδες µεθόδων στο Collection<T> Interface (7/10) 14
Κεφαλίδες µεθόδων στο Collection<T> Interface (8/10) 15
Κεφαλίδες µεθόδων στο Collection<T> Interface (9/10) 16
Κεφαλίδες µεθόδων στο Collection<T> Interface (10/10) 17
Collection Relationships Υπάρχει ένας αριθµός προκαθορισµένων κλάσεων που υλοποιούν το Collection<T> interface Οι κλάσεις που ορίζονται από τον προγραµµατιστή µπορούν επίσης να το υλοποιούν Μια µέθοδος που γράφεται για να διαχειρίζεται µια παράµετρο του τύπου Collection<T> θα λειτουργεί για όλες αυτές τις κλάσεις Υπάρχουν δυο κύρια interfaces που κάνουν extend το Collection<T> interface: Το Set<T> interface και το List<T> interface 18
Collection Relationships Οι κλάσεις που υλοποιούν το Set<T> interface δεν επιτρέπουν σε ένα στοιχείο της κλάσης να εµφανίζεται περισσότερες από µια φορά Το Set<T> interface έχει τις ίδιες κεφαλίδες µεθόδων όπως και το Collection<T> interface, αλλά σε µερικές περιπτώσεις η σηµασιολογία του (semantics) (αποσκοπούµενη σηµασία) είναι διαφορετική Οι µέθοδοι που είναι προαιρετικές στο Collection<T> interface είναι απαιτούµενες στο Set<T> interface 19
Collection Relationships Οι κλάσεις που υλοποιούν το List<T> interface έχουν τα στοιχεία τους διατεταγµένα, όπως σε µια λίστα Τα στοιχεία δεικτοδοτούνται αρχίζοντας από το Μηδέν Μια κλάση που υλοποιεί το List<T> interface επιτρέπει στα στοιχεία να εµφανίζονται περισσότερες από µια φορά Το List<T> interface έχει περισσότερες κεφαλίδες µεθόδων από ότι το Collection<T> interface Μερικές από τις µεθόδους που κληρονοµούνται από το Collection<T> interface έχουν διαφορετική σηµασιολογία για το List<T> interface ΗκλάσηArrayList<T> υλοποιεί το List<T> interface 20
Μέθοδοι στο Set<T> Interface (1/10) 21
Μέθοδοι στο Set<T> Interface (2/10) 22
Μέθοδοι στο Set<T> Interface (3/10) 23
Μέθοδοι στο Set<T> Interface (4/10) 24
Μέθοδοι στο Set<T> Interface (5/10) 25
Μέθοδοι στο Set<T> Interface (6/10) 26
Μέθοδοι στο Set<T> Interface (7/10) 27
Μέθοδοι στο Set<T> Interface (8/10) 28
Μέθοδοι στο Set<T> Interface (9/10) 29
Μέθοδοι στο Set<T> Interface (10/10) 30
Μέθοδοι στο List<T> Interface (1/16) 31
Μέθοδοι στο List<T> Interface (2/16) 32
Μέθοδοι στο List<T> Interface (3/16) 33
Μέθοδοι στο List<T> Interface (4/16) 34
Μέθοδοι στο List<T> Interface (5/16) 35
Μέθοδοι στο List<T> Interface (6/16) 36
Μέθοδοι στο List<T> Interface (7/16) 37
Μέθοδοι στο List<T> Interface (8/16) 38
Μέθοδοι στο List<T> Interface (9/16) 39
Μέθοδοι στο List<T> Interface (10/16) 40
Μέθοδοι στο List<T> Interface (11/16) 41
Μέθοδοι στο List<T> Interface (12/16) 42
Μέθοδοι στο List<T> Interface (13/16) 43
Μέθοδοι στο List<T> Interface (14/16) 44
Μέθοδοι στο List<T> Interface (15/16) 45
Μέθοδοι στο List<T> Interface (16/16) 46
Παγίδα: Προαιρετικές λειτουργίες Όταν ένα interface δίνει µια µέθοδο ως προαιρετική, αυτή η µέθοδος πρέπει να υλοποιηθεί από την κλάση που υλοποιεί το interface Το προαιρετικό σηµαίνει ότι επιτρέπεται να γράψουµε µια µέθοδο που δεν υλοποιεί εξ ολοκλήρου την αποσκοπούµενη σηµασιολογία Όµως, εάν δοθεί µια απλοϊκή υλοποίηση, τότε το σώµα τηςµεθόδου θα πρέπει να πετάξει µια UnsupportedOperationException 47
Υπόδειξη: ιαχείριση αυτών των Εξαιρέσεων Ητεκµηρίωση των µεθόδων διαφόρων collection interfaces και κλάσεων σηµατοδοτούν ότι πετάγονται κάποιες εξαιρέσεις Αυτές είναι unchecked exceptions, και άρα είναι χρήσιµες για αποσφαλµάτωση, αλλά δεν χρειάζεται να δηλωθούν ή να πιαστούν Στις υπάρχουσες collection κλάσεις, αντιµετωπίζονται ως run-time µηνύµατα λάθους Σε µια παραγόµενη κλάση κάποιας άλλης collection κλάσης, οι περισσότερες ή όλες από αυτές θα κληρονοµηθούν Σε µια collection κλάση που αναπτύσσεται από την αρχή, εάν πρόκειται να υλοποιεί κάποιο collection interface, τότε θα πρέπει να πετάει τις εξαιρέσεις που είναι καθορισµένες στο interface 48
Concrete Collections κλάσεις Η concrete κλάση HashSet<T> υλοποιεί το Set<T> interface, και µπορεί να χρησιµοποιηθεί εάν δεν απαιτούνται επιπλέον µέθοδοι ΗκλάσηHashSet<T> υλοποιεί όλες τις µεθόδους του Set<T> interface, και προσθέτει µόνο constructors ΗκλάσηHashSet<T> υλοποιείται µε χρήσηενόςπίνακα κατακερµατισµού (hash table) Οι κλάσεις ArrayList<T> και Vector<T> υλοποιούν το List<T> interface, και µπορούν να χρησιµοποιηθούν εάν δεν απαιτούνται επιπλέον µέθοδοι Τα interfaces ArrayList<T> και Vector<T> υλοποιούν όλες τις µεθόδους του interface List<T> Οποιαδήποτε από τις δυο κλάσεις µπορεί να χρησιµοποιηθεί όταν απαιτείται µια List<T> µε τυχαία προσπέλαση στα στοιχεία της 49
Concrete Collections κλάσεις Η concrete κλάση LinkedList<T> είναι µια concrete παραγόµενη κλάση της abstract κλάσης AbstractSequentialList<T> Όταν χρειαζόµαστε αποδοτική σειριακή µετακίνηση µέσα σε µια λίστα, θα πρέπει να χρησιµοποιείται η κλάση LinkedList<T> Το interface SortedSet<T> και η concrete κλάση TreeSet<T> σχεδιάστηκαν για υλοποιήσεις του Set<T> interface ώστε να παρέχουν γρήγορη ανάκτηση των στοιχείων Η υλοποίηση της κλάσης είναι παρόµοια µε έναδυαδικόδένδρο (binary tree), αλλά µε τρόπους εισαγωγής στοιχείων ώστε να διατηρείται το δένδρο ισοζυγισµένο 50
Μέθοδοι στην κλάση HashSet<T> (1/2) 51
Μέθοδοι στην κλάση HashSet<T> (2/2) 52
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (1/15) 53
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (2/15) 54
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (3/15) 55
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (4/15) 56
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (5/15) 57
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (6/15) 58
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (7/15) 59
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (8/15) 60
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (9/15) 61
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (10/15) 62
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (11/15) 63
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (12/15) 64
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (13/15) 65
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (14/15) 66
Μέθοδοι στις κλάσεις ArrayList<T> και Vector<T> (15/15) 67
ιαφορές ArrayList<T> και Vector<T> Για τους περισσότερους σκοπούς, οι ArrayList<T> και Vector<T> είναι ισοδύναµες ΗκλάσηVector<T> είναι παλιότερη, και έπρεπε να προστεθούν νέες µέθοδοι για να χωρέσει στο πλαίσιο των collection ΗκλάσηArrayList<T> είναι νεότερη, και δηµιουργήθηκε ως τµήµα του πλαισίου collection ΗκλάσηArrayList<T> υποτίθεται ότι είναι πιο αποδοτική από ότι η κλάση Vector<T> 68
Παγίδα: Παραλείποντας το <T> Όταν το <T> ή το αντίστοιχο όνοµα κλάσης παραλείπεται από µια reference σε µια collection κλάση, αυτό είναι λάθος για το οποίο ο compiler µπορεί ή όχι να σηµατοδοτήσει µήνυµα λάθους(εξαρτάται από τις λεπτοµέρειες του κώδικα), και ακόµα και όταν το κάνει, το µήνυµα λάθους µπορεί να είναι παράξενο Ψάχνουµε για παραληφθέν <T> ή <ClassName> όταν ένα πρόγραµµα χρησιµοποιεί collection κλάσεις και δίνει παράξενα µηνύµατα λάθους ή δεν εκτελείται σωστά 69
Το Map Framework Το Java map framework σχετίζεται µε συλλογές διατεταγµένων ζευγών Για παράδειγµα, ένα key και µια σχετιζόµενη τιµή Τα αντικείµενα στο map framework µπορεί να υλοποιούν µαθηµατικές συναρτήσεις και σχέσεις, και έτσι µπορεί να χρησιµοποιηθούν για να κατασκευάσουµε κλάσεις κατάλληλες για βάσεις δεδοµένων Το map framework χρησιµοποιεί το Map<T> interface, την AbstractMap<T> κλάση, και τις κλάσεις που παράγονται από την κλάση AbstractMap<T> 70
Iterators Ο iterator είναι ένα αντικείµενο που χρησιµοποιείται σε µια collection για να παράσχει σειριακή πρόσβαση στα στοιχεία της collection Η προσπέλαση επιτρέπει εξέταση και πιθανή τροποποίηση των στοιχείων Ο iterator επιβάλλει διάταξη στα στοιχεία της collection ακόµα καιότανηcollection δεν επιβάλλει κάποια διάταξη Εάν η collection επιβάλλει κάποια διάταξη, τότε ο iterator θα χρησιµοποιήσει την ίδια διάταξη 71
Το Iterator<T> interface Η Java παρέχει το Iterator<T> interface Οποιοδήποτε αντικείµενο µιαςκλάσηςπουικανοποιείτο Iterator<T> interface είναι ένας Iterator<T> Ένας Iterator<T> δεν υπάρχει από µόνος του Πρέπει να συσχετιστεί µε κάποιοαντικείµενο collection object µε χρήσητηςµεθόδου iterator Εάν c είναι ένα στιγµιότυπο (instance) µιας collection κλάσης (π.χ., HashSet<String>), η επόµενη δήλωση δίνει έναν iterator για το c: Iterator iteratorforc = c.iterator(); 72
Μέθοδοι στο Iterator<T> Interface (1/2) 73
Μέθοδοι στο Iterator<T> Interface (2/2) 74
Χρήση iterator µε αντικείµενο HashSet<T> Ένα αντικείµενο HashSet<T> δεν επιβάλλει διάταξη στα στοιχεία του Όµως, ο iterator θα βάλει κάποια διάταξη στα στοιχεία του hash set Η διάταξη αυτή προέρχεται από τη σειρά µε την οποία παράγονται από τη µέθοδο next() 75
Ένας Iterator (1/3) 76
Ένας Iterator (2/3) 77
Ένας Iterator (3/3) 78
Υπόδειξη: Βρόχοι For-Each ως iterators Παρόλο που δεν είναι iterator, ένας βρόχος foreach µπορεί να υπηρετήσει τον ίδιο σκοπό µε κάποιον iterator Χρησιµοποιούµε το βρόχο για να ανακυκλωνόµαστε στα στοιχεία µιας collection Οι βρόχοι For-each µπορεί να χρησιµοποιηθούν µε οποιαδήποτε από τις collections που παρουσιάσαµε 79
Βρόχοι For-Each ως Iterators (1/2) 80
Βρόχοι For-Each ως Iterators (2/2) 81
Το ListIterator<T> interface To ListIterator<T> interface extends to Iterator<T> interface, και σχεδιάστηκε για να λειτουργεί µε collections που ικανοποιούν το List<T> interface Το ListIterator<T> έχει όλες τις µεθόδους που έχει και ένα Iterator<T>, αλλά και επιπλέον µεθόδους Το ListIterator<T> επιτρέπει µετακίνηση και προς τις δυο κατευθύνσεις µιας λίστας Το ListIterator<T> έχει µεθόδους, όπως οι set και add, που µπορούν να χρησιµοποιηθούν για τροποποίηση των στοιχείων 82
Μέθοδοι στο ListIterator<T> Interface (1/4) 83
Μέθοδοι στο ListIterator<T> Interface (2/4) 84
Μέθοδοι στο ListIterator<T> Interface (3/4) 85
Μέθοδοι στο ListIterator<T> Interface (4/4) 86
The ListIterator<T> Cursor Κάθε ListIterator<T> έχει έναν position marker γνωστό ως cursor Εάν η λίστα έχει n στοιχεία, αυτά αριθµούνται µε δείκτες από 0 µέχρι n-1, αλλά υπάρχουν n+1 cursor positions Όταν ενεργοποιείται η next(), επιστρέφεται το στοιχείο που είναι αµέσως µετά την cursor position και ο cursor µετακινείται µια θέση προς τα εµπρός Όταν ενεργοποιείται η previous(), επιστρέφεται το στοιχείο που είναι αµέσως πριν την cursor position και ο cursor µετακινείται µια θέση προς τα πίσω 87
Θέσεις του ListIterator<T> Cursor 88
Παγίδα: Οι next και previous µπορεί να επιστρέφουν reference Θεωρητικά, όταν µια λειτουργία ενός iterator επιστρέφει ένα στοιχείο µιας collection, µπορεί να επιστρέφει ένα copy ή clone του στοιχείου, ή µπορεί να επιστρέφει µια reference στο στοιχείο Οι iterators για τις standard προκαθορισµένες collection κλάσεις, όπως τις ArrayList<T> και HashSet<T>, επιστρέφουν references Εποµένως, τροποποιώντας την επιστρεφόµενη τιµή, τροποποιούµε τοστοιχείοτηςcollection 89
Iterator που επιστρέφει reference (1/4) 90
Iterator που επιστρέφει reference (2/4) 91
Iterator που επιστρέφει reference (3/4) 92
Iterator που επιστρέφει reference (4/4) 93