====== Interfaces java.util.Map και java.util.SortedMap ====== Τα παραπάνω //interfaces// επιτρέπουν την αντιστοίχιση τιμών σε κλειδιά. Σκεφτείτε για παράδειγμα το ΑΕΜ σας, όπου είναι ένα μοναδικό κλειδί πάνω στο οποίο είναι συνδεδεμενη πληροφορία σχετικά με τα προσωπικά σας στοιχεία, τα μαθήματα που έχετε εξεταστεί, τα μαθήματα που έχετε επιτύχει και τη βαθμολογία κάθε μαθήματος κ.α. Σε αναλογία μία δομή τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html|java.util.Map]] επιτρέπει την αντιστοίχιση κλειδιών σε τιμές. Τόσο τα κλειδιά, όσο και οι τιμές οφείλουν να είναι αντικείμενα. ===== Το interface java.util.Map.Entry ===== Ένα αντικείμενο τύπου //[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html|java.util.Map.Entry]]// περιέχει ένα "κλειδί" και μία "τιμή" που αντιστοιχεί σε αυτό το κλειδί. Οι μέθοδοι του interface Map.Entry δίνονται στον παρακάτω πίνακα. {{ :java:map-entry.png |}} ===== Το interface java.util.Map ===== Μία δομή τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html|java.util.Map]] είναι μία δομή που περιέχει εγγραφές τύπου //Map.Entry// με τον περιορισμό ότι δεν μπορεί να διαθέτει δύο εγγραφές με το ίδιο κλειδί (μπορεί όμως να διαθέτει δύο εγγραφές με διαφορετικά κλειδιά, αλλά κοινές τιμές για τα κλειδιά αυτά). Βασικό χαρακτηριστικό μίας δομής τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html|java.util.Map]] είναι ότι δεν υπάρχει δυνατότητα διάτρεξης της δομής. Μπορείτε να εξετάσετε εάν υπάρχει ένα κλειδί, να διαγράψετε την εγγραφή που αντιστοιχεί σε ένα κλειδί, να διατρέξετε τα κλειδιά της δομής, να διατρέξετε τις τιμές της δομής, αλλά δεν σας δίνεται η δυνατότητα να διατρέξετε τις εγγραφές τύπου Map.Entry. Διαθέτει τις εξής μεθόδους που δεν διατίθενται στο interface //Collection// ή έχουν διαφορετική λειτουργία από τα interfaces που είδαμε μέχρι τώρα. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#containsKey(java.lang.Object)|containsKey(Object key)]] -** Επιστρέφει true αν η δομή περιέχει το συγκεκριμένο κλειδί * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#containsValue(java.lang.Object)|containsValue(Object value)]] -** Επιστρέφει true αν η δομή περιέχει την συγκεκριμένη τιμή αντιστοιχισμένη με ένα ή περισσότερα κλειδιά. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#remove(java.lang.Object)|remove(Object key)]] -** Διαγράφει την εγγραφή που αντιστοιχεί στο κλειδί //key// επιστρέφοντας την τιμή V ή null αν δεν βρέθηκε το κλειδί. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#replace-K-V-|replace(K key, V value)]] -** Αντικαθιστά την εγγραφή που αντιστοιχεί στο κλειδί //key// επιστρέφοντας την τιμή V. Δεν γίνεται αντικατάσταση αν δεν βρεθεί το κλειδί στο Map. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#put(K,%20V)|put(K key, V value)]] -** A Διαγράφει την εγγραφή που αντιστοιχεί στο κλειδί //key// επιστρέφοντας την τιμή V ή null αν δεν υπήρχε προηγούμενη καταχώρηση για το συγκεκριμένο κλειδί. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#get(java.lang.Object)|get(Object key)]] -** Επιστρέφει την τιμή που αντιστοιχεί στο δεδομένο κλειδί ή null αν δεν υπάρχει καταχώρηση για το συγκεκριμένο κλειδί. ==== Μετατροπή του Map σε μορφή που να μπορείτε να το διατρέξετε (Collection ή Set) ==== * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#entrySet()|entrySet()]] -** Επιστρέφει ένα //Set// από καταχωρήσεις τύπου //Entry.Map// όπου κάθε καταχώρηση περιέχει το συνδυασμό κλειδί-τιμή. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#values()|values()]] -** Επιστρέφει ένα //Collection// με τις τιμές του //Map// δίχως τα κλειδιά. Μία τιμή μπορεί να εμφανίζεται περισσότερες από μία φορές αν αντιστοιχεί σε περισσότερα του ενός κλειδιά. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#keySet()|keySet()]] -** Επιστρέφει ένα //Set// με τα κλειδιά. ===== Το interface java.util.SortedMap ===== Τo interface [[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html|java.util.SortedMap]] είναι ένα //Map// διαθέτει τις εγγραφές ταξινομημένες με βάση τα κλειδιά . Ένα [[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html|java.util.SortedMap]] υλοποιείται συνήθως μέσω ενός ισοζυγισμένου δυαδικού δέντρου. Οι επιπλέον μέθοδοι του συγκεκριμένου interface είναι οι εξής: * **[[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#firstKey()|firstKey()]] - ** Επιστρέφει το 1ο κλειδί. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#lastKey()|lastKey()]] - ** Επιστρέφει το τελευταίο κλειδί. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#headMap(K)|headMap(K toKey)]] - ** Επιστρέφει το υποσύνολο του Map που τα κλειδιά του είναι μικρότερα από την τιμή //toKey//. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#tailMap(K)|tailMap(K fromKey)]] - ** Επιστρέφει το υποσύνολο του Map που τα κλειδιά του του είναι μεγαλύτερα ή ίσα από την τιμή //fromKey//. * **[[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html#subMap(K,%20K)|subMap(K fromKey, K toKey)]] - ** Επιστρέφει το υποσύνολο του Set από fromKey (μαζί με το fromKey) έως toKey (χωρίς το toKey). ===== Υλοποιήσεις ===== Βασικές υλοποιήσεις του [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] interface είναι οι παρακάτω: * **[[https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html|HashMap]]:** Υλοποιεί το Map μέσα από ένα [[wp>Hash_table|HashTable]]. Γρήγορο στην αναζήτηση. Δεν εγγυάται ότι η σειρά διάτρεξης είναι η σειρά με την οποία εισάγαμε τα δεδομένα. Απαιτεί κατά κανόνα περισσότερο χώρο αποθήκευσης από τον στοιχεία που περιέχει το Map. Η κλάση που υλοποιεί το κλειδί κάθε εγγραφής πρέπει να υλοποιεί τις μεθόδους [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-|public boolean equals(Object obj)]] και [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--|public int hashCode()]] της κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html|java.lang.Object]]. * **[[https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html|TreeMap]]:** Υλοποιεί το Map μέσα από ένα [[wp>Red-black_tree|Red-Black tree]]. Ικανοποιητικά γρήγορο. Δεν εγγυάται ότι η σειρά διάτρεξης είναι η σειρά με την οποία εισάγαμε τα δεδομένα. Η σειρά διάτρεξης είναι η σειρά κατάταξης των στοιχείων (υλοποιεί τον interface [[http://docs.oracle.com/javase/7/docs/api/java/util/SortedMap.html|SortedMap]]). Η κλάση που υλοποιεί το κλειδί κάθε εγγραφής πρέπει να υλοποιεί το //interface// [[https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html|java.lang.Comparable]]. * **[[https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html|LinkedHashMap]]:** Υλοποιεί το Map μέσα από ένα [[wp>Hash_table|HashTable]] με παράλληλη χρήση διπλά συνδεδεμένης λίστας. Γρήγορο στην αναζήτηση. Εγγυάται ότι η σειρά διάτρεξης είναι η σειρά με την οποία εισάγαμε τα δεδομένα, λόγω της ύπαρξης της λίστας. Απαιτεί κατά κανόνα περισσότερο χώρο αποθήκευσης από τον στοιχεία που περιέχει το Map. Η κλάση που υλοποιεί το κλειδί κάθε εγγραφής πρέπει να υλοποιεί τις μεθόδους [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object-|public boolean equals(Object obj)]] και [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--|public int hashCode()]] της κλάσης [[https://docs.oracle.com/javase/8/docs/api/java/lang/Object.html|java.lang.Object]]. ===== Παράδειγμα 1ο ===== /* Παραλλάσουμε το παράδειγμα της λίστας, ώστε από τη λίστα να φτιαχτεί ένα ιστόγραμμα το οποίο δείχνει κάθε λέξη πόσες φορές εμφανίζεται μέσα στο κείμενο. Το ιστόγραμμα μπορεί να φτιαχτεί με τη βοήθεια ενός ''Map'', όπου τα κλειδιά είναι οι λέξεις του κειμένου και οι τιμές είναι η συχνότητα εμφάνισης της λέξης μέσα στο κείμενο. import java.util.*; import java.io.*; public class MapExample { public static void main(String []args) { List wordsList = new ArrayList<>(); try(Scanner sc = new Scanner(new File(args[0]))) { while(sc.hasNext()) { String word = sc.next().toLowerCase(); wordsList.add(word); } Map wordHistogram= new TreeMap<>(); Iterator it = wordsList.iterator(); while(it.hasNext()) { String word = it.next(); if(wordHistogram.containsKey(word)) wordHistogram.put(word, wordHistogram.get(word) + 1); else wordHistogram.put(word, 1); } for(String word : wordHistogram.keySet()) System.out.println(word+" -> "+ wordHistogram.get(word)); } catch(FileNotFoundException ex) { System.out.println("Unable to open file \""+args[0]+"\""); } } } Τι θα γίνει εάν στο παραπάνω παράδειγμα αντί για [[https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html|java.util.TreeMap]] χρησιμοποιήσουμε [[https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html|java.util.HashMap]]; Σημειώστε ότι η κλάση [[https://docs.oracle.com/javase/8/docs/api/java/util/TreeMap.html|java.util.TreeMap]] υλοποιεί τα interfaces [[https://docs.oracle.com/javase/8/docs/api/java/util/Map.html|java.util.Map]] και [[https://docs.oracle.com/javase/8/docs/api/java/util/SortedMap.html|java.util.SortedMap]], ενώ η κλάση [[https://docs.oracle.com/javase/8/docs/api/java/util/HashMap.html|java.util.HashMap]] μόνο τη interface [[https://docs.oracle.com/javase/8/docs/api/java/util/Map.html|java.util.Map]]. Δοκιμάστε το... ===== Παράδειγμα 2ο ===== */ import java.util.*; public class StudentMap { public static void printMapEntries(Map map) { Set> set = map.entrySet(); Iterator> it = set.iterator(); while(it.hasNext()) { Map.Entry entry = it.next(); System.out.println(entry.getKey() + " -> "+ entry.getValue() ); } } public static void printMapValues(Map map) { Collection coll = map.values(); Iterator it = coll.iterator(); while(it.hasNext()) { System.out.println(it.next().toString()); } } public static void printMapKeys(Map map) { Set set = map.keySet(); Iterator it = set.iterator(); while(it.hasNext()) { System.out.println(it.next().toString()); } } public static void main(String args[]) { Map students = new HashMap<>(); students.put(1, new Student("John", "Smith")); students.put(2, new Student("Stanley", "Peters")); students.put(3, new Student("Edgar", "Bloch")); students.put(4, new Student("Suzan", "Miles")); students.put(5, new Student("Mary", "Poppins")); System.out.println("\nMap keys are:"); printMapKeys(students); System.out.println("\nMap values are:"); printMapValues(students); System.out.println("\nMap key-value pairs are:"); printMapEntries(students); } } |Προηγούμενο: [[:java:jfc_intf_list | Interface java.util.List ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:jfc_algorithms | Αλγόριθμοι ]] |