Both sides previous revisionPrevious revisionNext revision | Previous revision |
java:jfc_intf_map [2017/02/07 21:20] – [Μετατροπή του Map σε μορφή που να μπορείτε να το διατρέξετε (Collection ή Set)] gthanos | java:jfc_intf_map [Unknown date] (current) – external edit (Unknown date) 127.0.0.1 |
---|
====== java.util.Map ====== | ====== Interfaces java.util.Map και java.util.SortedMap ====== |
| |
Ένα αντικείμενο τύπου //[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html|Map.Entry]]// αντιστοιχεί "τιμές" σε "κλειδιά". Τόσο οι τιμές όσο και τα κλειδιά μπορεί να είναι οποιουδήποτε τύπου. Ο στόχος της συγκεκριμένης δομής είναι να μπορούμε έχοντας το κλειδί να λάβουμε την τιμή που αντιστοιχεί σε αυτό. Οι μέθοδοι του interface Map.Entry δίνονται στον παρακάτω πίνακα. | Τα παραπάνω //interfaces// επιτρέπουν την αντιστοίχιση τιμών σε κλειδιά. Σκεφτείτε για παράδειγμα το ΑΕΜ σας, όπου είναι ένα μοναδικό κλειδί πάνω στο οποίο είναι συνδεδεμενη πληροφορία σχετικά με τα προσωπικά σας στοιχεία, τα μαθήματα που έχετε εξεταστεί, τα μαθήματα που έχετε επιτύχει και τη βαθμολογία κάθε μαθήματος κ.α. Σε αναλογία μία δομή τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html|java.util.Map]] επιτρέπει την αντιστοίχιση κλειδιών σε τιμές. Τόσο τα κλειδιά, όσο και οι τιμές οφείλουν να είναι αντικείμενα. |
{{ :java:map-entry.png |}} | |
| |
Μία δομή τύπου [[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] είναι μία δομή που περιέχει εγγραφές τύπου //Map.Entry// με την ιδιαιτερότητα ότι δεν μπορεί να διαθέτει δύο εγγραφές με το ίδιο κλειδί (μπορεί όμως να διαθέτει δύο εγγραφές με διαφορετικά κλειδιά, αλλά ίδιες τιμές). | ===== Το interface java.util.Map.Entry ===== |
| |
Η java διατηρεί τρεις βασικές κλάσεις που υλοποιούν το //[[http://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]], [[https://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html|TreeMap]] και [[https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html|LinkedHashMap]]. | Ένα αντικείμενο τύπου //[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.Entry.html|java.util.Map.Entry]]// περιέχει ένα "κλειδί" και μία "τιμή" που αντιστοιχεί σε αυτό το κλειδί. Οι μέθοδοι του interface Map.Entry δίνονται στον παρακάτω πίνακα. |
| {{ :java:map-entry.png |}} |
| |
Βασικές υλοποιήσεις του [[https://docs.oracle.com/javase/7/docs/api/java/util/Map.html|Map]] interface είναι οι παρακάτω: | ===== Το interface java.util.Map ===== |
* **[[https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html|HashMap]]:** Υλοποιεί το Map μέσα από ένα [[wp>Hash_table|HashTable]]. Γρήγορο στην αναζήτηση. Δεν εγγυάται ότι η σειρά διάτρεξης είναι η σειρά με την οποία εισάγαμε τα δεδομένα. Απαιτεί κατά κανόνα περισσότερο χώρο αποθήκευσης από τον στοιχεία που περιέχει το Map. | |
* **[[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]]). | |
* **[[https://docs.oracle.com/javase/7/docs/api/java/util/LinkedHashMap.html|LinkedHashMap]]:** Υλοποιεί το Map μέσα από ένα [[wp>Hash_table|HashTable]] με παράλληλη χρήση διπλά διασυνδεδεμένης λίστας. Γρήγορο στην αναζήτηση. Εγγυάται ότι η σειρά διάτρεξης είναι η σειρά με την οποία εισάγαμε τα δεδομένα, λόγω της ύπαρξης της λίστας. Απαιτεί κατά κανόνα περισσότερο χώρο αποθήκευσης από τον στοιχεία που περιέχει το 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 που είδαμε μέχρι τώρα. | Διαθέτει τις εξής μεθόδους που δεν διατίθενται στο interface //Collection// ή έχουν διαφορετική λειτουργία από τα interfaces που είδαμε μέχρι τώρα. |
* **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#keySet()|keySet()]] -** Επιστρέφει ένα //Set// με τα κλειδιά. | * **[[http://docs.oracle.com/javase/7/docs/api/java/util/Map.html#keySet()|keySet()]] -** Επιστρέφει ένα //Set// με τα κλειδιά. |
| |
<code java StudentMap.java> | ===== Το 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<String,Integer>'', όπου τα κλειδιά είναι οι λέξεις του κειμένου και οι τιμές είναι η συχνότητα εμφάνισης της λέξης μέσα στο κείμενο. |
| |
| <code java MapExample.java> |
import java.util.*; | import java.util.*; |
import java.lang.*; | import java.io.*; |
| |
public class StudentMap { | public class MapExample { |
| |
private Map<Integer,Student> students; | public static void main(String []args) { |
| |
public StudentMap() { | List<String> wordsList = new ArrayList<>(); |
students = new LinkedHashMap<Integer,Student>(); | try(Scanner sc = new Scanner(new File(args[0]))) { |
populateMap(); | while(sc.hasNext()) { |
| String word = sc.next().toLowerCase(); |
| wordsList.add(word); |
| } |
| |
| Map<String,Integer> wordHistogram= new TreeMap<>(); |
| Iterator<String> 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]+"\""); |
| } |
} | } |
| } |
| |
| </code> |
| |
| <WRAP todo 80% center round> |
| Τι θα γίνει εάν στο παραπάνω παράδειγμα αντί για [[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]]. Δοκιμάστε το... |
| </WRAP> |
| |
| ===== Παράδειγμα 2ο ===== |
| */ |
| <code java StudentMap.java> |
| import java.util.*; |
| |
| public class StudentMap { |
| |
public final void populateMap() { | public static void printMapEntries(Map<Integer,Student> map) { |
students.put(1, new Student("John", "Smith")); | Set<Map.Entry<Integer,Student>> set = map.entrySet(); |
students.put(2, new Student("Stanley", "Peters")); | Iterator<Map.Entry<Integer,Student>> it = set.iterator(); |
students.put(3, new Student("Edgar", "Bloch")); | |
students.put(4, new Student("Suzan", "Miles")); | |
students.put(5, new Student("Mary", "Poppins")); | |
} | |
| |
public void iterateMapEntries() { | |
Set set = students.entrySet(); | |
Iterator it = set.iterator(); | |
while(it.hasNext()) { | while(it.hasNext()) { |
System.out.println(it.next().toString()); | Map.Entry<Integer,Student> entry = it.next(); |
| System.out.println(entry.getKey() + " -> "+ entry.getValue() ); |
} | } |
} | } |
| |
public void iterateMapValues() { | public static void printMapValues(Map<Integer,Student> map) { |
Collection col = students.values(); | Collection<Student> coll = map.values(); |
Iterator it = col.iterator(); | Iterator<Student> it = coll.iterator(); |
while(it.hasNext()) { | while(it.hasNext()) { |
System.out.println(it.next().toString()); | System.out.println(it.next().toString()); |
} | } |
| |
public void iterateMapKeys() { | public static void printMapKeys(Map<Integer,Student> map) { |
Set set = students.keySet(); | Set<Integer> set = map.keySet(); |
Iterator it = set.iterator(); | Iterator<Integer> it = set.iterator(); |
while(it.hasNext()) { | while(it.hasNext()) { |
System.out.println(it.next().toString()); | System.out.println(it.next().toString()); |
| |
public static void main(String args[]) { | public static void main(String args[]) { |
StudentMap stl = new StudentMap(); | Map<Integer,Student> students = new HashMap<>(); |
System.out.println("Map keys are:"); | students.put(1, new Student("John", "Smith")); |
stl.iterateMapKeys(); | students.put(2, new Student("Stanley", "Peters")); |
System.out.println("Map values are:"); | students.put(3, new Student("Edgar", "Bloch")); |
stl.iterateMapValues(); | students.put(4, new Student("Suzan", "Miles")); |
System.out.println("Map key-value pairs are:"); | students.put(5, new Student("Mary", "Poppins")); |
stl.iterateMapEntries(); | |
| |
| 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); |
} | } |
} | } |
</code> | </code> |
| |
|Προηγούμενο: [[:java:jfc_intf_Map | Interface java.util.Map ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:jfc_intf_sort | Sorting ]] | | |Προηγούμενο: [[:java:jfc_intf_list | Interface java.util.List ]] | [[:toc | Περιεχόμενα ]] | Επόμενο: [[:java:jfc_algorithms | Αλγόριθμοι ]] | |
| |
| |
| |