مماثلة
مماثل هو واجهة الفرز.
إذا كان الفصل يطبق الواجهة المماثلة ، فهذا يعني "هذه الفئة تدعم الفرز". نظرًا لأن الفصول التي تنفذ فرز واجهة مماثلة ، على افتراض أن هناك الآن "قائمة قائمة (أو صفيف) من كائنات الفئات التي تنفذ واجهة قابلة للمقارنة" ، يمكن فرز قائمة القائمة (أو الصفيف) بواسطة collections.sort (أو المصفوفات).
بالإضافة إلى ذلك ، يمكن استخدام "كائن الفئة التي تنفذ واجهة قابلة للمقارنة" كمفتاح في "الخريطة المطلوبة (مثل treemap)" أو عنصر في "مجموعة مرتبة (Treeset)" دون تحديد المقارنة.
تتضمن الواجهة المماثلة وظيفة واحدة فقط ، وتعريفها على النحو التالي:
حزمة java.lang ؛ استيراد java.util.*؛ الواجهة العامة قابلة للمقارنة <T> {public int compareto (t o) ؛} الوصف: لنفترض أننا "نقارن أحجام X و Y" من خلال x.compareto (y). إذا قمت بإرجاع "رقم سالب" ، فهذا يعني أن "X أصغر من Y" ؛ إذا قمت بإرجاع "صفر" ، فهذا يعني أن "X يساوي Y" ؛ إذا قمت بإرجاع "رقم إيجابي" ، فهذا يعني أن "X أكبر من Y".
كانت الواجهة المماثلة عامة ، وبالتالي فإن الكائن الذي ينفذ قابلة للمقارنة يعلن نوعه الذي يمكن مقارنته. (بشكل عام ، هذا هو نوع الكائن نفسه ، لكنه قد يكون أيضًا فئة من الوالدين في بعض الأحيان.)
الواجهة العامة قابلة للمقارنة {Public Boolean Compareto (T other) ؛ }
لذلك ، تحتوي الواجهة المماثلة على معلمة type t ، وهو نوع الكائن الذي يمكن أن يقارنه الفئة التي تنفذ قابلة للمقارنة. هذا يعني أنه إذا قمت بتحديد فئة تنفذ قابلة للمقارنة ، مثل السلسلة ، يجب أن تعلن ليس فقط المقارنة بين الفئة ، ولكن أيضًا ما يمكن أن يقارن به (عادةً مع نفسه):
سلسلة الفئة العامة تنفذ قابلة للمقارنة {...}
الآن دعونا نفكر في تنفيذ طريقة MAX () الثنائية. تريد قبول معلمتين من نفس النوع ، كلاهما قابلة للمقارنة وقابل للمقارنة مع بعضهما البعض. لحسن الحظ ، هذا أمر بديهي تمامًا إذا كنت تستخدم طرقًا عامة ومعلمات النوع المقيد:
public static> t max (t t1 ، t t2) {if (t1.compareto (t2)> 0) return t1 ؛ عودة أخرى T2 ؛ }
في هذا المثال ، تقوم بتحديد طريقة عامة تم توليدها على النوع T ، وتقيد امتداد النوع (التنفيذ) قابلة للمقارنة. يجب أن تكون كلتا المعلمتين من النوع T ، مما يعني أنهما من نفس النوع ، ومقارنة الدعم ، ويمكن مقارنتها ببعضها البعض. سهل!
والأفضل من ذلك ، أن برنامج التحويل البرمجي سيستخدم نوعًا من النوع لتحديد معنى قيمة t عند استدعاء Max (). لذلك ليست هناك حاجة لتحديد T على الإطلاق ، ستعمل المكالمة التالية:
سلسلة s = max ("moo" ، "bark") ؛سيحسب المترجم أن القيمة المحددة مسبقًا لـ T هي سلسلة ، لذلك سيؤدي التجميع والتحقق من النوع. ولكن إذا حاولت استدعاء Max () مع وسيط إلى الفئة X التي لا تنفذ قابلة للمقارنة ، فلن يسمح المترجم بذلك.
المقارنة
المقارنة هي واجهة المقارنة.
إذا كنا بحاجة إلى التحكم في ترتيب فئة معينة ، والتي لا تدعم الفرز بحد ذاتها (أي ، فإنها لا تنفذ الواجهة المماثلة) ؛ ثم يمكننا إنشاء "مقارنة لهذه الفئة" لفرز. يحتاج هذا "المقارنة" فقط إلى تنفيذ واجهة المقارنة.
وهذا يعني أنه يمكننا إنشاء مقارنة جديدة من خلال "تطبيق فئة المقارنة" ، ثم فرز الفصل من خلال المقارنة.
تتضمن واجهة المقارنة وظيفتين فقط ، وتعريفها على النحو التالي:
حزمة java.util ؛ مقارن الواجهة العامة <T> {int compare (t o1 ، t o2) ؛ منطقية متساوية (كائن OBJ) ؛} يوضح:
1. إذا أراد فئة ما تنفيذ واجهة المقارنة: يجب أن تنفذ وظيفة المقارنة (T O1 ، T O2) ، ولكنها قد لا تنفذ وظيفة (Object OBJ).
لماذا لا يمكننا تنفيذ وظيفة (Object OBJ)؟ لأنه بشكل افتراضي ، تم تنفيذ متساو (كائن OBJ). جميع الفئات في Java موروثة من java.lang.object ، ويتم تنفيذ وظيفة equals (Object OBJ) في object.java ؛ لذلك ، فإن جميع الفئات الأخرى تعادل تنفيذ هذه الوظيفة.
2.int مقارنة (T O1 ، T O2) هو "قارن أحجام O1 و O2". إرجاع "الرقم السلبي" يعني "O1 أصغر من O2" ؛ إرجاع "صفر" ، بمعنى "O1 يساوي O2" ؛ إرجاع "الرقم الإيجابي" يعني "O1 أكبر من O2".
المقارنة والقابلة للمقارنة
قابلة للمقارنة هي واجهة الفرز. إذا قام الفصل بتنظيم واجهة مماثلة ، فهذا يعني "هذه الفئة تدعم الفرز".
المقارنة هو مقارن. إذا احتجنا إلى التحكم في ترتيب فئة معينة ، فيمكننا إنشاء "مقارنة لهذه الفئة" لفرزها.
ليس من الصعب العثور على أن المقارنة تعادل "المقارنة الداخلية" ، في حين أن المقارنة تعادل "المقارنة الخارجية".
نستخدم برنامج اختبار لتوضيح هاتين الواجهتين. رمز المصدر كما يلي:
استيراد java.util.* ؛ import java.lang.comparable ؛/*** deSc مقارنة بين "المقارنة" و "قابلة للمقارنة". * (01) "قابلة للمقارنة" * وهي واجهة فرز تحتوي على وظيفة واحدة فقط (). * ينفذ الفصل الواجهة المماثلة ، مما يعني "الفئة نفسها تدعم الفرز" ، والتي يمكن فرزها مباشرة من خلال المصفوفات. * (02) "المقارنة" * إنها واجهة المقارنة ، بما في ذلك وظيفتين: مقارنة () ومتساوية (). * فئة تنفذ واجهة المقارنة ، فهو "مقارن". يمكن فرز فصول أخرى وفقًا للمقارنة. * * لتلخيص: قابلة للمقارنة هو مقارن داخلي ، في حين أن المقارنة هو مقارن خارجي. * فئة نفسها تنفذ مقارنة مماثلة ، مما يعني أنه يدعم الفرز ؛ إذا لم يتم تنفيذها المقارنة نفسها ، فيمكن أيضًا فرزها من خلال مقارنة المقارنة الخارجية. */الفئة العامة المقارنات ParetComparArandComparableTest {public static void main (string [] args) {// إنشاء ArrayList (صفيف ديناميكي) ArrayList <Pirons> قائمة = ArrayList New ArrayList <Phone> () ؛ // إضافة كائن إلى قائمة ArrayList.add (شخص جديد ("CCC" ، 20)) ؛ list.add (شخص جديد ("AAA" ، 30)) ؛ list.add (شخص جديد ("BBB" ، 10)) ؛ list.add (شخص جديد ("DDD" ، 40)) ؛ // طباعة التسلسل الأصلي لنظام القائمة. // فرز القائمة // هنا سيتم فرزها وفقًا لـ "واجهة <String> المماثلة التي يتم تنفيذها بواسطة الشخص" ، أي ، تم فرزها وفقًا لـ "Name" ، Collections.Sort (List) ؛ System.out.printf ("اسم الفرز ، القائمة: ٪ s/n" ، قائمة) ؛ // فرز القائمة من خلال "المقارنة (AscageComparator)" // طريقة الفرز لـ AscageComparator هي: يتم فرزها وفقًا للترتيب الصاعد لمجموعة "Age". System.out.printf ("ASC (AGE) SITE ، LIST: ٪ S/N" ، List) ؛ // فرز القائمة من خلال "المقارنة (descageComparator)". // طريقة الفرز لـ DescageComparator هي: الفرز وفقًا للترتيب التنازلي لمجموعات "العمر" system.out.printf ("desc (Age) sort ، list: ٪ s/n" ، list) ؛ // تحديد ما إذا كان الشخصان متساوون في اختبار () ؛ } /*** desc اختبار ما إذا كان الشخصان متساويان. * نظرًا لأن الشخص ينفذ وظيفة متساوية (): إذا كان عمر واسم الشخصين متساوتين ، فإن الشخصين يعتبران متساوين. * لذلك ، هنا P1 و P2 متساوية. * * TODO: إذا تمت إزالة الدالة المتساوية () في الشخص ، فإن P1 لا يساوي p2 */ private static void testequals () {person p1 = new شخص ("eee" ، 100) ؛ الشخص p2 = شخص جديد ("eee" ، 100) ؛ if (p1.equals (p2)) {system.out.printf ("٪ s equal ٪ s/n" ، p1 ، p2) ؛ } آخر {system.out.printf ("٪ s لا يساوي ٪ s/n" ، p1 ، p2) ؛ }} /*** @desc person class. * يقوم الشخص بتنفيذ الواجهة المماثلة ، مما يعني أن الشخص نفسه يدعم فرز الشخص الثابت*/ الشخص الثابت الخاص بتنفيذ <Phone> {int Age ؛ اسم السلسلة الشخص العام (اسم السلسلة ، int age) {this.name = name ؛ this.age = العمر ؛ } السلسلة العامة getName () {return name ؛ } public int getage () {return Age ؛ } السلسلة العامة toString () {return name + " -" + Age ؛ } / *** قارن ما إذا كان شخصان متساويان: إذا كان اسمهم وعمرهما متساويين ، فإنهما يعتبران متساوون* / boolean يساوي (شخص) {if (this.age == person.age && this.name == person.name) العودة كاذبة } /*** DESC قم بتنفيذ واجهة "قابلة للمقارنة <string>" ، أي ، أعد كتابة وظيفة المقارنة <T>. * فيما يلي مقارنة باسم "اسم الشخص"*/ Override public int compareto (شخص شخص) {return name.compareto (person.name) ؛ // إرجاع this.name - person.name ؛ }} / *** DESC ASCAGECOMPARATOR CAINTARTATOR* إنه "المقارنة الصعودية لعمر الشخص"* / الفئة الثابتة الخاصة التي تنفذها AscageComparator Paricator <Person> {Override Public int (PRIST P1 ، PRISE P2) {return p1.getage () - p2.getage () ؛ }} / *** descagecomparator المقارنة* إنه "مقارن تصاعدي لعمر الشخص"* / private static class descageComparator يمنع المقارن <profern> {Override public int (person p1 ، person p2) {return p2.getage () - p1.getage () ؛ }}} فيما يلي تفسير لهذا البرنامج.
1. التعريف الفئة الشخصي. على النحو التالي:
شخص فئة ثابتة خاصة ينفذ <Pirons> {int Age ؛ اسم السلسلة ... /*** DESC ينفذ واجهة "قابلة للمقارنة <string>" ، أي ، تجاوز وظيفة المقارنة <T>. * فيما يلي مقارنة باسم "اسم الشخص"*/ Override public int compareto (شخص شخص) {return name.compareto (person.name) ؛ // إرجاع this.name - person.name ؛ }} يوضح:
(1) يمثل فئة الشخص الشخص. هناك سمتان في فئة البيرونج: العمر (العمر) واسم "اسم الشخص".
(2) فئة الشخص تنفذ الواجهة المماثلة ، بحيث يمكن فرزها.
2. في Main () ، نقوم بإنشاء صفيف قائمة الشخص (قائمة). على النحو التالي:
// إنشاء ArrayList جديد (صفيف ديناميكي) ArrayList <Person> قائمة = ArrayList جديد <Person> () ؛ // إضافة كائن إلى قائمة ArrayList.add (شخص جديد ("CCC" ، 20)) ؛ list.add (شخص جديد ("AAA" ، 30)) 3. بعد ذلك ، نطبع جميع عناصر القائمة. على النحو التالي:
// طباعة التسلسل الأصلي لنظام القائمة.
4. ثم ، نفرز القائمة من خلال وظيفة المجموعات ().
نظرًا لأن الشخص ينفذ الواجهة المماثلة ، عند الفرز من خلال SORT () ، سيتم فرزه وفقًا لطريقة الفرز التي يدعمها الشخص ، أي القواعد المحددة بواسطة Compareto (الشخص). على النحو التالي:
// قم بفرز القائمة // هنا سنقوم بفرز وفقًا لـ "الواجهة المماثلة <string> التي تم تنفيذها بواسطة الشخص" ، أي الفرز وفقًا لـ "name" collections.sort (list) ؛ System.out.printf ("اسم الفرز ، القائمة: ٪ s/n" ، قائمة) ؛ 5. قابلة للمقارنة والمقارنة
نحدد مقارنتين ، AscageComparator و DescageComparator ، إلى الصعود إلى شخص منخفض على التوالي.
6.ASCAGECOMPARATOR المقارن ، فإنه يفرز الشخص في ترتيب تصاعدي حسب العمر. الرمز كما يلي:
/*** DESC ASCAGECOMPARATOR CAINTARATOR* إنه "مقارن تصاعدي لعمر الشخص"*/الفئة الثابتة الخاصة التي تنفذ ASCAGECOMPARATOR المقارن <Person> {Override Public int (PRISON P1 ، PRISE P2) {return p1.getage () - p2.getage () ؛ }} 7.DescageComparator مقارنة الشخص بفرز الشخص في ترتيب تنازلي حسب العمر. الرمز كما يلي:
/*** descescageComparator Comparator* إنه "مقارن تصاعدي لعمر الشخص"*/private static class descagecomparator يبرز المقارنة <profern> {Override public int (person p1 ، person p2) {return p2.getage () - p1.getage () ؛ }} 8. قم بتشغيل البرنامج نتيجة لذلك ، فإن الإخراج كما يلي:
الفرز الأصلي ، القائمة: [CCC - 20 ، AAA - 30 ، BBB - 10 ، DDD - 40] فرز الاسم ، القائمة: [AAA - 30 ، BBB - 10 ، CCC - 20 ، DDD - 40] - 20 ، BBB - 10] EEE - 100 EEE - 100