הממשק Comparator
חלק מהיחידה תכנות מונחה עצמים במסלול ה-Java של Coddy. שיעור 45 מתוך 87.
בעוד ש-Comparable מגדיר את הסדר הטבעי של מחלקה, לפעמים צריך למיין אובייקטים בדרכים שונות. הממשק Comparator מאפשר ליצור לוגיקת השוואה נפרדת בלי לשנות את המחלקה המקורית.
Comparator הוא אובייקט חיצוני שמשווה בין שני אובייקטים מאותו סוג. זה שימושי כשאתה רוצה כמה אפשרויות מיון או כשאינך יכול לשנות את המחלקה עצמה:
import java.util.Comparator;
class NameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getName().compareTo(p2.getName());
}
}
class AgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
return p1.getAge() - p2.getAge();
}
}לאחר מכן אפשר להעביר את המשווה למתודות מיון:
List<Person> people = new ArrayList<>();
people.add(new Person("Charlie", 30));
people.add(new Person("Alice", 25));
Collections.sort(people, new NameComparator()); // ממוין לפי שם
Collections.sort(people, new AgeComparator()); // ממוין לפי גילכדי לכתוב קוד תמציתי, אפשר להשתמש בביטויי lambda, מכיוון ש־Comparator הוא ממשק פונקציונלי:
Collections.sort(people, (p1, p2) -> p1.getName().compareTo(p2.getName()));ההבדל העיקרי: המחלקה שמשווים אותה מממשת את Comparable ומגדירה סדר טבעי אחד, ואילו Comparator היא מחלקה נפרדת שיכולה להגדיר מספר בלתי מוגבל של סדרים מותאמים אישית.
אתגר
קלבואו נבנה מערכת למיון עובדים שמדגימה את העוצמה של הממשק Comparator. תיצרו כמה משווים כדי למיין עובדים בדרכים שונות — לפי שכר ולפי שם — בלי לשנות את המחלקה Employee עצמה.
תארגנו את הקוד שלכם בארבעה קבצים:
Employee.java: צרו מחלקה שמייצגת עובד עם שלושה שדות פרטיים:name(String),department(String) ו-salary(double). כללו בנאי לאתחול כל השדות ומתודות getter עבור כל אחד מהם. דרסו אתtoString()כך שתחזיר:[name] ([department]) - $[salary]SalaryComparator.java: צרו משווה שממיין עובדים לפי שכר בסדר יורד (המשכורת הגבוהה ביותר תחילה). ממשו את הממשקComparator<Employee>ואת המתודהcompare()שלו. השתמשו ב-Double.compare()להשוואה בטוחה של ערכי השכר.NameComparator.java: צרו משווה נוסף שממיין עובדים לפי שם בסדר אלפביתי, בסדר עולה (מא' עד ת'). ממשו אתComparator<Employee>והשתמשו במתודתcompareTo()של String לצורך ההשוואה.Main.java: חברו את כל החלקים יחד על ידי יצירת רשימת עובדים ומיונם באמצעות המשווים שלכם. תקבלו קלט עבור שלושה עובדים, כל אחד בשורה נפרדת, בפורמט:name,department,salaryצרו
ArrayListשל עובדים, ואז הדגימו את שתי שיטות המיון:- תחילה, מיינו לפי שכר באמצעות
SalaryComparatorשלכם והדפיסו כל עובד - הדפיסו שורה ריקה
- לאחר מכן, מיינו לפי שם באמצעות
NameComparatorשלכם והדפיסו כל עובד
- תחילה, מיינו לפי שכר באמצעות
תקבלו שלוש שורות קלט, שכל אחת מהן מכילה נתוני עובד בפורמט: name,department,salary
לדוגמה, שורת קלט עשויה להיראות כך: Alice,Engineering,75000.0
זכרו לייבא את java.util.Comparator בקובצי המשווים שלכם, ואת java.util.ArrayList, java.util.Collections ו-java.util.Scanner בקובץ Main שלכם. שימו לב כיצד משווים מאפשרים לכם להגדיר כמה אסטרטגיות מיון באופן חיצוני: מחלקת Employee לא צריכה לדעת דבר על האופן שבו אפשר למיין אותה!
נסו בעצמכם
import java.util.ArrayList;
import java.util.Collections;
import java.util.Scanner;
class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// קראו שלושה עובדים מהקלט
// הפורמט של כל שורה: name,department,salary
String line1 = scanner.nextLine();
String line2 = scanner.nextLine();
String line3 = scanner.nextLine();
// TODO: נתחו כל שורה וצרו אובייקטים מסוג Employee
// רמז: השתמשו ב־split(",") כדי להפריד בין הערכים
// TODO: צרו ArrayList של עובדים והוסיפו אליו את שלושתם
// TODO: מיינו לפי שכר באמצעות SalaryComparator והדפיסו כל עובד
// רמז: השתמשו ב־Collections.sort(list, comparator)
// TODO: הדפיסו שורה ריקה
// TODO: מיינו לפי שם באמצעות NameComparator והדפיסו כל עובד
}
}
השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.
כל השיעורים ביחידה תכנות מונחה עצמים
1יסודות התכנות מונחה העצמים
קבצים חיצונייםמבוא לתכנות מונחה עצמיםמחלקות לעומת אובייקטיםמילת המפתח thisמתודותשדות (מאפיינים)מתודת הבנאיהעמסת בנאיםחזרה – מחשבון פשוט4ירושה
ירושה בסיסית (extends)מילת המפתח superדריסת מתודות (@Override)שרשור בנאיםהמחלקה Objectירושה יחידה ורב־רמתיתלמה אין ירושה מרובה של מחלקותסיכום – היררכיית עובדים7מתודות מיוחדות ומחלקת Object
מתודת toString()equals() ו-hashCode()מתודת clone()compareTo() ו-Comparableהממשק Comparatorסיכום – מיון מותאם אישית2מצייני גישה ואנקפסולציה
סקירה של רמות הגישהמתודות Getter ו-Setterהסתרת מידעמילת המפתח finalסיכום – מנהל חשבון בנק5פולימורפיזם
יסודות העמסת מתודותדריסת מתודות (בזמן ריצה)המרה כלפי מעלה וכלפי מטההאופרטור instanceofמחלקות ומתודות מופשטותסיכום – מחשבון צורות8מושגי OOP מתקדמים
הרכבה מול ירושהאגרגציה מול הרכבהמחלקות פנימיות, מקוננות ואנונימיותEnums ומתודות של EnumRecords (Java 16+)מחלקות חתומות (Java 17+)3מאפייני מחלקה וחברים סטטיים
משתני מופע לעומת משתנים סטטייםמתודות סטטיותבלוקים סטטייםקבועים (static final)סיכום — מונה ומחלקת עזר6ממשקים ומחלקות מופשטות
מבוא לממשקיםמימוש ממשקיםמימוש של כמה ממשקיםמתודות ברירת מחדל וסטטיות בממשקמחלקות מופשטות לעומת ממשקיםממשקים פונקציונלייםסיכום – מערכת תשלומיםתרגלו בעצמכם: קומפיילר Java אונליין