מדריך ל- Java 8 Comparator. השוואה ()

1. סקירה כללית

Java 8 הציגה מספר שיפורים ל- משווה ממשק, כולל קומץ פונקציות סטטיות שיש בהן תועלת רבה כשמגיעים סדר מיון לאוספים.

Java 8 lambdas ניתן למנף ביעילות עם משווה ממשק גם כן. הסבר מפורט על lambdas ו משווה ניתן למצוא כאן, וכרוניקה בנושא מיון ויישומים של משווה ניתן למצוא כאן.

במדריך זה, נחקור כמה פונקציות שהוצגו עבור משווה ממשק ב- Java 8.

2. תחילת העבודה

2.1. מחלק שעועית לדוגמא

לדוגמאות במאמר זה, בואו ליצור עוֹבֵד שעועית ולהשתמש בשדותיה לצורך השוואה ומיון:

שכבה ציבורית עובד {שם מחרוזת; גיל int; משכורת כפולה; נייד ארוך; // בונים, גטרים וקובעים}

2.2. נתוני הבדיקה שלנו

בואו גם ליצור מערך עובדים שישמש לאחסון התוצאות מהסוג שלנו במקרי מבחן שונים לאורך המאמר:

עובדים = עובד חדש [] {...};

הסדר הראשוני של אלמנטים של עובדים יהיה:

[עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

במהלך המאמר נבצע מיון למעלה עוֹבֵד מערך המשתמש בפונקציות שונות.

לקבלת קביעות בדיקה, נשתמש בקבוצת מערכים ממוינים מראש אותם נשווה לתוצאות המיון שלנו (כלומר, עובדים מערך) לתרחישים שונים.

בואו נכריז על כמה מערכים אלה:

@ לפני החלל פומבי initData () {sortedEmployeesByName = עובד חדש [] {...}; sortedEmployeesByNameDesc = עובד חדש [] {...}; sortedEmployeesByAge = עובד חדש [] {...}; // ...}

כמו תמיד, אל תהסס להפנות את קישור GitHub שלנו לקוד השלם.

3. שימוש Comparator. השוואה

סעיף זה מכסה גרסאות של Comparator. השוואה פונקציה סטטית.

3.1. וריאנט בורר מקשים

ה Comparator. השוואה פונקציה סטטית מקבלת מפתח מיון פוּנקצִיָה ומחזירה א משווה לסוג המכיל את מפתח המיון:

סטָטִי  השוואה בין השוואה (פונקציית מקש מחלץ)

כדי לראות זאת בפעולה, בואו נשתמש ב- שֵׁם שדה ב עוֹבֵד כמפתח המיון והעבירו את התייחסות השיטה שלו כטיעון מסוג פוּנקצִיָה. ה משווה מוחזר מאותו משמש למיון:

@ מבחן פומבי בטל כאשרComparing_thenSortedByName () {Comparator employeeNameComparator = Comparator.comparing (עובד :: getName); Arrays.sort (עובדים, עובד NameComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByName)); }

כפי שאתה יכול לראות, עובדים ערכי מערך ממוינים לפי שם כתוצאה מהמיון:

[עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)] 

3.2. בורר מקשים ו משווה גִרְסָה אַחֶרֶת

יש אפשרות נוספת המאפשרת לעקוף את הסדר הטבעי של מפתח המיון על ידי מתן ה- משווה שיוצר הזמנה מותאמת אישית למפתח המיון:

השוואה בין קומפקטי סטטי (פונקציית מקש מחלץ, מקדם קומפרטור)

בואו ונשתנה את המבחן לעיל ונעקוף את הסדר הטבעי של המיון לפי ה- שֵׁם שדה על ידי מתן א משווה למיון השמות בסדר יורד כטיעון השני ל- Comparator. השוואה:

@Test ציבורי בטל כאשרComparingWithComparator_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator.comparing (עובד :: getName, (s1, s2) -> {return s2.compareTo (s1);}); Arrays.sort (עובדים, עובד NameComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByNameDesc)); }

כפי שאתה יכול לראות, התוצאות ממוינות בסדר יורד לפי שֵׁם:

[עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001)]

3.3. באמצעות Comparator. הפוך

כאשר מופעל על הקיים משווה, שיטת המופע Comparator. הפוך מחזיר חדש משווה זה הופך את סדר המיון של המקור.

בואו נשתמש ב- משווה שממיין את העובדים לפי שֵׁם ו לַהֲפוֹך כך שעובדים ממוינים לפי סדר יורד של שֵׁם:

@ מבחן ציבורי בטל כאשרReversed_thenSortedByNameDesc () {Comparator employeeNameComparator = Comparator.comparing (עובד :: getName); Comparator employeeNameComparatorReversed = employeeNameComparator.reversed (); Arrays.sort (עובדים, עובדNameComparatorReversed); assertTrue (Arrays.equals (עובדים, sortedEmployeesByNameDesc)); }

התוצאות ממוינות בסדר יורד לפי שֵׁם:

[עובד (שם = קית ', גיל = 35, משכורת = 4000.0, נייד = 3924401), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001)]

3.4. באמצעות Comparator.comparingInt

יש גם פונקציה Comparator.comparingInt שעושה את אותו הדבר כמו Comparator. השוואה, אבל זה לוקח רק int סלקטורים. בואו ננסה זאת עם דוגמה בה אנו מזמינים עובדים על ידי גיל:

@ מבחן ציבורי בטל כאשרComparingInt_thenSortedByAge () {Comparator employeeAgeComparator = Comparator.comparingInt (עובד :: getAge); Arrays.sort (עובדים, עובדAgeComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByAge)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

3.5. באמצעות Comparator.comparingLong

דומה למה שעשינו בשבילו int מקשים, בואו נראה דוגמה באמצעות Comparator.comparingLong לשקול מפתח מיון מסוג ארוך על ידי הזמנת עובדים מערך לפי נייד שדה:

@ מבחן ציבורי בטל כאשרComparingLong_thenSortedByMobile () {Comparator employeeMobileComparator = Comparator.comparingLong (עובד :: getMobile); Arrays.sort (עובדים, עובד MobileComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByMobile)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון עם נייד כמפתח:

[עובד (שם = קית ', גיל = 35, משכורת = 4000.0, נייד = 3924401), עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001)]

3.6. באמצעות Comparator.comparingDouble

שוב, דומה למה שעשינו בשבילו int ו ארוך מקשים, בואו נראה דוגמה באמצעות Comparator.comparingDouble לשקול מפתח מיון מסוג לְהַכפִּיל על ידי הזמנת עובדים מערך לפי שכר שדה:

@ מבחן ציבורי בטל כאשרComparingDouble_thenSortedBySalary () {Comparator employeeSalaryComparator = Comparator.comparingDouble (עובד :: getSalary); Arrays.sort (עובדים, עובדSalaryComparator); assertTrue (Arrays.equals (עובדים, מיונים עובדים שכירים)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון עם שכר כמפתח המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

4. שוקל סדר טבעי ב משווה

הסדר הטבעי מוגדר על ידי התנהגות ה- ניתן להשוות יישום ממשק. מידע נוסף על ההבדל בין משווה ושימושים ב ניתן להשוות ממשק ניתן למצוא במאמר זה.

בואו ניישם ניתן להשוות בשלנו עוֹבֵד בכיתה כדי שנוכל לנסות את הזמנה טבעית ו סדר הפוך פונקציות של משווה מִמְשָׁק:

מחלקה ציבורית מיישמת עובדים השוואה {// ... @Override public int CompareTo (עובד / ת עובד / ת עובד) {return name.compareTo (argEmployee.getName ()); }}

4.1. שימוש בסדר טבעי

ה הזמנה טבעית הפונקציה מחזירה את משווה לסוג ההחזרה המוזכר בחתימה:

סטָטִי  הזמנה טבעית ()

בהתחשב בהיגיון הנ"ל כדי להשוות עובדים על סמך שֵׁם שדה, בואו נשתמש בפונקציה זו כדי להשיג ל- a משווה אשר ממיין את עובדים מערך בסדר טבעי:

@Test ציבורי בטל whenNaturalOrder_thenSortedByName () {Comparator employeeNameComparator = השווה. הזמנה טבעית (); Arrays.sort (עובדים, עובד NameComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByName)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

4.2. שימוש בסדר טבעי הפוך

דומה ל הזמנה טבעית, בואו נשתמש ב- סדר הפוך שיטה ליצור משווה אשר תייצר סדר הפוך של עובדים לזה שב הזמנה טבעית דוגמא:

@Test ציבורי בטל כאשרReverseOrder_thenSortedByNameDesc () {Comparator employeeNameComparator = השווה. סדר הפוך(); Arrays.sort (עובדים, עובד NameComparator); assertTrue (Arrays.equals (עובדים, sortedEmployeesByNameDesc)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[עובד (שם = קית ', גיל = 35, משכורת = 4000.0, נייד = 3924401), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001)]

5. התחשבות בערכים אפסיים בהשוואה

סעיף זה מכסה פונקציות nulls ראשית ו nullsLast, אשר שוקלים ריק ערכים בסדר ושמור על ריק ערכים בתחילת או בסוף רצף ההזמנה.

5.1. שוקל את Null First

בואו נכניס באופן אקראי ריק ערכים ב עובדים מַעֲרָך:

[עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), null, עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001), null, עובד (שם = Keith, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

ה nulls ראשית הפונקציה תחזיר א משווה זה שומר על הכל אפסים בתחילת רצף ההזמנה:

@ מבחן ציבורי בטל כאשר NullsFirst_thenSortedByNameWithNullsFirst () {Comparator employeeNameComparator = Comparator.comparing (עובד :: getName); Comparator employeeNameComparator_nullFirst = Comparator.nullsFirst (עובד שם-תואם); Arrays.sort (workersArrayWithNulls, employeeNameComparator_nullFirst); assertTrue (Arrays.equals (workersArrayWithNulls, מיוןעובדים Array_WithNullsFirst)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[null, null, עובד (שם = Ace, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = John, גיל = 25, משכורת = 3000.0, mobile = 9922001), עובד (שם = Keith, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

5.2. שוקל את Null Last

ה nullsLast הפונקציה תחזיר א משווה זה שומר על הכל אפסים בסוף רצף ההזמנה:

@ מבחן ציבורי בטל כאשר NullsLast_thenSortedByNameWithNullsLast () {Comparator employeeNameComparator = Comparator.comparing (עובד :: getName); Comparator employeeNameComparator_nullLast = Comparator.nullsLast (עובד NameComparator); Arrays.sort (workersArrayWithNulls, employeeNameComparator_nullLast); assertTrue (Arrays.equals (workersArrayWithNulls, sortedEmployeesArray_WithNullsLast)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ון, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401), null, null]

6. שימוש Comparator. ואז השוואה

ה ואזהשוואה פונקציה מאפשרת לך להגדיר סדר ערכים לקסיקוגרפיים על ידי הקצאת מקשי מיון מרובים ברצף מסוים.

בואו ניקח בחשבון מערך אחר של עוֹבֵד מעמד:

someMoreEmployees = עובד חדש [] {...};

שקול את רצף האלמנטים הבא במערך שלעיל:

[עובד (שם = ג'ייק, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = ג'ייק, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = Ace, גיל = 22, משכורת = 3000.0, נייד = 6423001), עובד (שם = קית, גיל = 35, משכורת = 4000.0, נייד = 3924401)]

בוא נכתוב רצף השוואות כ- גיל ואחריו שֵׁם וראה את הסדר של מערך זה:

@ מבחן ציבורי בטל כאשרThenComparing_thenSortedByAgeName () {Comparator employee_Age_Name_Comparator = Comparator.comparing (עובד :: getAge) .thenComparing (עובד :: getName); Arrays.sort (someMoreEmployees, employee_Age_Name_Comparator); assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByAgeName)); }

כאן ההזמנה תיעשה על ידי גיל, ועבור הערכים עם אותו הדבר גיל, ההזמנה תיעשה על ידי שֵׁם. בואו נצפה בזה ברצף שנקבל לאחר המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 3000.0, נייד = 6423001), עובד (שם = ג'ייק, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ייק, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית ', גיל = 35, משכורת = 4000.0, נייד = 3924401)]

בואו נשתמש בגרסה השנייה של ואזהשוואה זה ואזהשוואה, על ידי שינוי הרצף הלקסיקוגרפי ל- שֵׁם בא אחריו גיל:

@Test ציבורי בטל כאשרThenComparing_thenSortedByNameAge () {Comparator עובד_Name_Age_Comparator = Comparator.comparing (עובד :: getName) .thenComparingInt (עובד :: getAge); Arrays.sort (כמה עובדים יותר, עובד_שם_גיל) assertTrue (Arrays.equals (someMoreEmployees, sortedEmployeesByNameAge)); }

בוא נראה איך ה עובדים ערכי מערך מסודרים לאחר המיון:

[עובד (שם = אייס, גיל = 22, משכורת = 3000.0, נייד = 6423001), עובד (שם = ג'ייק, גיל = 22, משכורת = 2000.0, נייד = 5924001), עובד (שם = ג'ייק, גיל = 25, משכורת = 3000.0, נייד = 9922001), עובד (שם = קית ', גיל = 35, משכורת = 4000.0, נייד = 3924401)]

באופן דומה, יש פונקציות ואזהשוואהLong ו ואזComparingDouble לשימוש ארוך ו לְהַכפִּיל מפתחות מיון.

7. מסקנה

מאמר זה הוא מדריך למספר תכונות שהוצגו ב- Java 8 עבור משווה מִמְשָׁק.

כרגיל, את קוד המקור ניתן למצוא ב- Github.