Presentation is loading. Please wait.

Presentation is loading. Please wait.

Containers ב Java אליהו חלסצ'י תכנות מתקדם תרגול מספר 3

Similar presentations


Presentation on theme: "Containers ב Java אליהו חלסצ'י תכנות מתקדם תרגול מספר 3"— Presentation transcript:

1 Containers ב Java אליהו חלסצ'י תכנות מתקדם 89-210 תרגול מספר 3
תשע"א Containers ב Java אליהו חלסצ'י

2 הקדמה ב java אין templates
במקום, ישנה קבוצה של collections, שיכולה לספק את רוב הצרכים שלנו ב containers קבוצה זו לא נבנתה לשם יעילות כמו ה STL של C++ בעבר קבוצה זו עבדה עם הטיפוס Object וכך היה ניתן להכניס פנימה כל מופע מכל מחלקה אך העבודה עם Object מצריכה casting וזה האט את הביצועים, כיום ניתן להגדיר את הטיפוס המוכנס ל container לא ניתן להכניס primitive types ל containers, משום שדרוש אובייקט, לכן יש את המחלקות העוטפות כדוגמת Integer כמובן שהדבר צורך יותר זיכרון...

3 Comparator נניח שנרצה למיין רשימה, פעם בסדר עולה ופעם בסדר יורד, האם נצטרך לשם כך שני מימושים? התשובה היא לא, אם משתמשים ב Strategy Pattern ע"פ תבנית זו, אלגוריתם המיון ישתמש בהחלטה מבחוץ כיצד למיין את הרשימה כדי להשפיע על שיטת המיון ב Containers השונים ב java, משתמשים בתבנית זו באמצעות comparator

4 Comparator כל מחלקה יכולה לממש את הממשקים הבאים:
ע"פ המימוש באחד מממשקים אלו, ה containers מחליטים כיצד למיין בפנים את העצמים השמורים interface Comparator { int compare(Object o1, Object o2); } interface Comparable { int compareTo(Object o) ; }

5 Comparator דוגמא: פלט: aaabc aabc abc
Robot r1=new RV1(); Robot r2=new RV1(); Robot r3=new RV1(); r1.setName("aaabc"); r2.setName("aabc"); r3.setName("abc"); ArrayList<Robot> ar=new ArrayList<Robot>(); ar.add(r3); ar.add(r2); ar.add(r1); Collections.sort(ar); for(int i=0;i<ar.size();i++){ System.out.println(ar.get(i).getName()); } פלט: aaabc aabc abc public class RV1 implements Robot ,Comparable<Robot>{ private String name; public String getName() { return name; } public int compareTo(Robot arg0) { return name.compareTo(arg0.getName()); } מיון: אופטימיזציה של merge sort מהירה ויציבה: מיון מהיר: nlog(n) תמיד מובטח (בניגוד ל quick sort) עובד מהר יותר על רשימות כמעט ממוינות. מיון יציב : - לא ממיינת עצמים שווים. (דוג' דואר שממוין לפי תאריך)

6 Containers שימושיים ב java יש שני סוגים של Containers:
Collections קבוצה של ערכים בודדים List – רשימה: שומר על הערכים ברצף מסוים Set – קבוצה: אותו הערך לא יכול להופיע יותר מפעם אחת Map קבוצה של הזוגות מפתח + ערך לכל אלו מימושים שונים על בסיס הצורות שלמדתם בקורס מבנה נתונים לכל אחד יתרונות וחסרונות אחרים, ולכן יש להתאים את ה container לדרישות התוכנה

7 Containers שימושיים להלן כמה דוגמאות: List Set Map
ArrayList ממומש על בסיס מערך: גישה אקראית מהירה, אך הוספה ומחיקה מהאמצע איטית LinkedList ממומש על בסיס רשימה מקושרת דו כיוונית: גישה אקראית איטית, אך הוספה ומחיקה מהאמצע מהירה Set HashSet לשימוש כשזמן חיפוש האלמנט חשוב, יש לממש המתודה HashCode() לאובייקט שברצוננו להכניס TreeSet ניתן בקלות להוציא רשימה ממוינת Map HashMap ממומש באמצעות hash tables, אובייקט המפתח חייב לממש את HashCode() LinkedHashMap – אותו הדבר, אך שומר גם את סדר ההכנסה TreeMap – ממומש ע"י עץ אדום שחור, ניתן לקבל תוצאות ממוינות

8 Containers שימושיים מתודות שימושיות ל Collections:
boolean add(Objetc o) boolean add(Collection c) void clear() boolean contains(Object o) boolean isEmpty() Iterator iterator() boolean remove(Object o) boolean removeAll(Collection c) int size() Object[] toArray()

9 Containers שימושיים מתודות שימושיות ל Map:
Object put(Object key, Object value) void putAll(Map t) Object get(Object key) void clear() boolean containsKey(Object key) boolean containsValue(Object value) boolean isEmpty() Object remove(Object key) int size() Set entrySet() Set keySet() Collection values()

10 Iterator מטרת ה Iterator היא לספק גישה לעצמים ב Container מבלי לחשוף את אופן פעולתו בממשק (של List לדוג') לא ניתן לספק את כל האופנים השונים בהם נרצה לטייל ב container ייתכנו כמה iterators עבור אותו ה container כל אחד יטייל בדרך שונה על העצמים

11 Iterator דוגמאות: ArrayList<Robot> ar=new ArrayList<Robot> (); ar.add(r3); ar.add(r2); ar.add(r1); for(int i=0;i<ar.size();i++){ System.out.println(ar.get(i).getName()); } for(Robot r : ar){ System.out.println(r.getName()); Iterator<Robot> it=ar.iterator(); while (it.hasNext()){ System.out.println(it.next().getName()); על arrayList אפשר לרוץ כמו מערך וגם באמצעות iterator

12 Iterator דוגמאות: HashSet HashMap
HashSet hs<Robot>=new HashSet<Robot> (); hs.add(r3); hs.add(r2); hs.add(r1); Iterator<Robot> it=hs.iterator(); while (it.hasNext()){ System.out.println(it.next().getName()); } דוגמאות: HashSet HashMap String key; HashMap<String,Robot> hm=new HashMap<String,Robot> (); hm.put(r3.getName(), r3); hm.put(r2.getName(), r2); hm.put(r1.getName(), r1); Iterator<String> it=hm.keySet().iterator(); while (it.hasNext()){ key=it.next(); System.out.println(hm.get(key).getName()); } על arrayList אפשר לרוץ כמו מערך וגם באמצעות iterator

13 Iterator דרכים נוספות לעבור על HashMap
for(Entry<String,Robot> e : hm.entrySet()) System.out.println(e.getKey()+","+e.getValue()); for(String k : hm.keySet()) System.out.println(k+","+hm.get(k)); for(Robot r : hm.values()) System.out.println(r); על arrayList אפשר לרוץ כמו מערך וגם באמצעות iterator

14 Factory Pattern בעיה: נניח שיש לנו n סוגים של אובייקטים ולכל אחד שם, אופן פעולת התוכנית צריך להיות כך שהמשתמש בכל פעם בוחר שם והאובייקט הרצוי נוצר לכאורה, במקרה הגרוע צריך n השוואות כדי לדעת באיזה שם המשתמש בחר, וע"פ השם הזה ליצור את האובייקט הרצוי.  O(n) דרך טובה יותר לפתור את הבעיה, היא להשתמש ב Factory Pattern, יש הרבה דרכים למימוש, נראה דוגמא לדרך אחת

15 Factory Pattern ניצור ממשק עם הפקודה create.
private HashMap<String,RobotFac> robotFactory; public RobotFactory(){ robotFactory=new HashMap<String,RobotFac> (); robotFactory.put("RV1", new RV1Fac()); robotFactory.put("RV2", new RV2Fac()); robotFactory.put("Aibo", new AiboFac()); } public Robot createRobot(String type){ return robotFactory.get(type).create(); import java.util.HashMap; public class RobotFactory { private interface RobotFac{ public Robot create(); } private class RV1Fac implements RobotFac{ public Robot create(){ return new RV1();} private class RV2Fac implements RobotFac{ public Robot create(){ return new RV2();} private class AiboFac implements RobotFac{ public Robot create(){ return new Aibo();} ניצור ממשק עם הפקודה create.

16 Factory Pattern ניצור ממשק עם הפקודה create.
private HashMap<String,RobotFac> robotFactory; public RobotFactory(){ robotFactory=new HashMap<String,RobotFac> (); robotFactory.put("RV1", new RV1Fac()); robotFactory.put("RV2", new RV2Fac()); robotFactory.put("Aibo", new AiboFac()); } public Robot createRobot(String type){ return robotFactory.get(type).create(); import java.util.HashMap; public class RobotFactory { private interface RobotFac{ public Robot create(); } private class RV1Fac implements RobotFac{ public Robot create(){ return new RV1();} private class RV2Fac implements RobotFac{ public Robot create(){ return new RV2();} private class AiboFac implements RobotFac{ public Robot create(){ return new Aibo();} ניצור ממשק עם הפקודה create. נממש את הממשק ע"י מחלקות עבור כל אחד מסוגי האובייקטים הרצויים.

17 Factory Pattern ניצור ממשק עם הפקודה create.
private HashMap<String,RobotFac> robotFactory; public RobotFactory(){ robotFactory=new HashMap<String,RobotFac> (); robotFactory.put("RV1", new RV1Fac()); robotFactory.put("RV2", new RV2Fac()); robotFactory.put("Aibo", new AiboFac()); } public Robot createRobot(String type){ return robotFactory.get(type).create(); import java.util.HashMap; public class RobotFactory { private interface RobotFac{ public Robot create(); } private class RV1Fac implements RobotFac{ public Robot create(){ return new RV1();} private class RV2Fac implements RobotFac{ public Robot create(){ return new RV2();} private class AiboFac implements RobotFac{ public Robot create(){ return new Aibo();} ניצור ממשק עם הפקודה create. נממש את הממשק ע"י מחלקות עבור כל אחד מסוגי האובייקטים הרצויים. ניצור HashMap עבור המחלקות הנ"ל, כשהמפתח הוא השם דרכו המשתמש בוחר ליצור את האובייקט הרצוי.

18 Factory Pattern ניצור ממשק עם הפקודה create.
private HashMap<String,RobotFac> robotFactory; public RobotFactory(){ robotFactory=new HashMap<String,RobotFac> (); robotFactory.put("RV1", new RV1Fac()); robotFactory.put("RV2", new RV2Fac()); robotFactory.put("Aibo", new AiboFac()); } public Robot createRobot(String type){ return robotFactory.get(type).create(); import java.util.HashMap; public class RobotFactory { private interface RobotFac{ public Robot create(); } private class RV1Fac implements RobotFac{ public Robot create(){ return new RV1();} private class RV2Fac implements RobotFac{ public Robot create(){ return new RV2();} private class AiboFac implements RobotFac{ public Robot create(){ return new Aibo();} ניצור ממשק עם הפקודה create. נממש את הממשק ע"י מחלקות עבור כל אחד מסוגי האובייקטים הרצויים. ניצור HashMap עבור המחלקות הנ"ל, כשהמפתח הוא השם דרכו המשתמש בוחר ליצור את האובייקט הרצוי. נכניס את הזוגות String, RobotFac>> ל Hashmap

19 Factory Pattern ניצור ממשק עם הפקודה create.
private HashMap<String,RobotFac> robotFactory; public RobotFactory(){ robotFactory=new HashMap<String,RobotFac> (); robotFactory.put("RV1", new RV1Fac()); robotFactory.put("RV2", new RV2Fac()); robotFactory.put("Aibo", new AiboFac()); } public Robot createRobot(String type){ return robotFactory.get(type).create(); import java.util.HashMap; public class RobotFactory { private interface RobotFac{ public Robot create(); } private class RV1Fac implements RobotFac{ public Robot create(){ return new RV1();} private class RV2Fac implements RobotFac{ public Robot create(){ return new RV2();} private class AiboFac implements RobotFac{ public Robot create(){ return new Aibo();} ניצור ממשק עם הפקודה create. נממש את הממשק ע"י מחלקות עבור כל אחד מסוגי האובייקטים הרצויים. ניצור HashMap עבור המחלקות הנ"ל, כשהמפתח הוא השם דרכו המשתמש בוחר ליצור את האובייקט הרצוי. נכניס את הזוגות String, RobotFac>> ל Hashmap פקודת יצירת האובייקט: בהינתן מחרוזת שהמשתמש בחר, ניגש בזמן של O(1) ל HashMap אל האובייקט השמור תחת אותה המחרוזת כמפתח נקרא ל create ונקבל את האובייקט הרצוי. החלפנו O(n) זמן ב O(n) מקום, וקיבלנו זמן של O(1) ליצירת אובייקטים + נוחות לתחזק ולהוסיף בעתיד או אובייקטים ל Factory.

20 Trove העובדה ש containers מקבלים אובייקט מצריכה אותנו לבזבז זיכרון בעקבות השימוש במחלקות העוטפות, במקרה שאנו רוצים להשתמש רק ב primitive types הקבוצה GNU Trove יצרה Collections חדשים שמקבלים primitive types ובכך חוסכות זיכרון, וכן משפרת משמעותית את הביצועים באתר הקורס פרטים על הורדה + הדרך להוסיף jars לפרויקט באמצעות ה eclipse

21 Trove קוד לדוגמא: פלט: last value for key1 was 0.2 key: 2 , value: 0.2
import gnu.trove.*; public class HelloWorldApp { static TByteFloatHashMap hm=new TByteFloatHashMap(); public static void main(String[] args) { float lastValueForThisKey; byte key1=1,key2=2,key3=3; hm.put(key1, (float) 0.2); lastValueForThisKey=hm.put(key1, (float) 0.1); System.out.println("last value for key1 was "+lastValueForThisKey); hm.put(key2, (float) 0.2); hm.put(key3, (float) 0.3); TByteFloatIterator it= hm.iterator(); while (it.hasNext()){ it.advance(); System.out.println("key: "+it.key()+" , value: "+ it.value()); } פלט: last value for key1 was 0.2 key: 2 , value: 0.2 key: 1 , value: 0.1 key: 3 , value: 0.3

22 הטמעה מנה 2 חסרונות של ה containers ב java לעומת C++ STL
באיזה אלגוריתם מיון משתמש Collections.sort() ומדוע? בדקו האם המתודה boolean contains(Object o) מחזירה "אמת" לפי תוכן האובייקט או לפי מיקומו בזיכרון כנסו לאתר Sun ותכירו עוד containers כגון PriorityQueue, Hashtable צרו collection כלשהו עבור int באמצעות trove ותעברו עליו באמצעות iterator


Download ppt "Containers ב Java אליהו חלסצ'י תכנות מתקדם תרגול מספר 3"

Similar presentations


Ads by Google