ہائے! آج ہم اشیاء کا موازنہ کرنے کے بارے میں بات کرنے جا رہے ہیں۔
ہمم... لیکن کیا ہم پہلے ہی اس موضوع پر ایک سے زیادہ بار بات نہیں کر چکے ہیں؟ :/ ہم جانتے ہیں کہ
میں کب استعمال کروں
مثال کے طور پر، فرض کریں کہ ہمیں 15٪ وقت کی طرح ترتیب دینے کی ضرورت ہے۔

==
آپریٹر کیسے کام کرتا ہے، ساتھ ہی equals()
اور hashCode()
طریقے بھی۔ موازنہ تھوڑا مختلف ہے۔ اس سے پہلے، ہمارا غالباً مطلب تھا "مساوات کے لیے اشیاء کی جانچ کرنا"۔ لیکن اشیاء کا ایک دوسرے سے موازنہ کرنے کی وجوہات بالکل مختلف ہو سکتی ہیں! ان میں سب سے واضح چھانٹنا ہے۔ میرے خیال میں اگر آپ کو نمبروں یا تاروں کو ترتیب دینے کے لیے کہا جائے ArrayList<>
تو آپ اسے بغیر کسی پریشانی کے سنبھال سکیں گے:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
String name1 = "Masha";
String name2 = "Sasha";
String name3 = "Dasha";
List<String> names = new ArrayList<>();
names.add(name1);
names.add(name2);
names.add(name3);
Collections.sort(names);
System.out.println(names);
}
}
کنسول آؤٹ پٹ:
[Dasha, Masha, Sasha]
اگر آپ کو Collections
کلاس اور اس کا sort()
طریقہ یاد ہے تو شاباش! مجھے لگتا ہے کہ آپ کو بھی نمبروں کے ساتھ کوئی پریشانی نہیں ہوگی۔ یہاں آپ کے لیے ایک زیادہ مشکل کام ہے:
public class Car {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
// ...getters, setters, toString()
}
import java.util.ArrayList;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
}
}
کام دراصل آسان ہے۔ ہمارے پاس ایک Car
کلاس اور 3 کار آبجیکٹ ہیں۔ کیا آپ برائے مہربانی فہرست میں کاروں کو ترتیب دیں گے؟ آپ شاید پوچھیں گے، "انہیں کیسے ترتیب دیا جائے؟" نام کے ساتھ؟ تیاری کے سال کی طرف سے؟ زیادہ سے زیادہ رفتار سے؟ بہترین سوال۔ اس وقت، ہم نہیں جانتے کہ Car
اشیاء کو کیسے ترتیب دیا جائے۔ اور، بالکل فطری طور پر، جاوا کو یہ بھی نہیں معلوم! جب ہم اشیاء کی فہرست کو طریقہ Car
میں منتقل کرنے کی کوشش کرتے ہیں Collections.sort()
، تو ہمیں ایک خرابی ملتی ہے:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(20012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
// Compilation error!
Collections.sort(cars);
}
}
اور درحقیقت، زبان کو یہ کیسے معلوم ہوگا کہ آپ کی لکھی ہوئی کلاسوں کی اشیاء کو کیسے ترتیب دیا جائے؟ یہ اس بات پر منحصر ہے کہ آپ کے پروگرام کو کیا کرنے کی ضرورت ہے۔ ہمیں کسی نہ کسی طرح جاوا کو ان اشیاء کا موازنہ کرنا سکھانا چاہیے۔ اور ان کا موازنہ کرنا جس طرح ہم چاہتے ہیں۔ جاوا کے پاس اس کے لیے ایک خاص طریقہ کار ہے: Comparable
انٹرفیس۔ کسی نہ کسی طرح ہماری اشیاء کا موازنہ اور ترتیب دینے کے لیے Car
، کلاس کو اس انٹرفیس کو نافذ کرنا چاہیے، جو کہ ایک طریقہ پر مشتمل ہے: compareTo()
:
public class Car implements Comparable<Car> {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
@Override
public int compareTo(Car o) {
return 0;
}
// ...getters, setters, toString()
}
براہ مہربانی نوٹ کریںکہ ہم نے Comparable<Car>
انٹرفیس کی وضاحت کی، نہ صرف Comparable
۔ یہ ایک پیرامیٹرائزڈ انٹرفیس ہے، یعنی ہمیں مخصوص متعلقہ کلاس کی وضاحت کرنی چاہیے۔ اصولی طور پر، آپ <Car>
انٹرفیس سے ہٹا سکتے ہیں، لیکن پھر موازنہ Object
ڈیفالٹ کے ذریعہ اشیاء پر مبنی ہوگا۔ طریقہ کے بجائے compareTo(Car o)
، ہماری کلاس میں یہ ہوگا:
@Override
public int compareTo(Object o) {
return 0;
}
یقیناً، ہمارے لیے اس کے ساتھ کام کرنا بہت آسان ہے Car
۔ طریقہ کار کے اندر compareTo()
، ہم کاروں کا موازنہ کرنے کے لیے اپنی منطق کو نافذ کرتے ہیں۔ فرض کریں کہ ہمیں انہیں تیاری کے سال کے لحاظ سے ترتیب دینے کی ضرورت ہے۔ آپ نے شاید محسوس کیا ہے کہ compareTo()
طریقہ ایک واپس کرتا ہے int
، a نہیں boolean
۔ یہ آپ کو حیران نہ ہونے دیں۔ جب ہم دو اشیاء کا موازنہ کرتے ہیں تو 3 امکانات ہوتے ہیں:
а < b
a > b
a == b
.
boolean
اس کی صرف 2 اقدار ہیں: صحیح اور غلط، جو اشیاء کا موازنہ کرنے کے لیے اچھی طرح سے کام نہیں کرتی ہیں۔ کے ساتھ int
، سب کچھ بہت آسان ہے۔ اگر واپسی کی قیمت ہے > 0
تو a > b
. اگر کا نتیجہ compareTo
ہے < 0
، تو a < b
۔ اور، اگر نتیجہ ہے == 0
، تو دو اشیاء برابر ہیں: a == b
۔ تیاری کے سال کے لحاظ سے کاروں کو ترتیب دینا ہماری کلاس کو سکھانا آسان ہے:
@Override
public int compareTo(Car o) {
return this.getManufactureYear() - o.getManufactureYear();
}
لیکن یہاں کیا ہو رہا ہے؟ ہم ایک کار آبجیکٹ ( this
) لیتے ہیں، اس کار کی تیاری کا سال حاصل کرتے ہیں، اور اس سے دوسری کار کی تیاری کا سال گھٹاتے ہیں (جس کے ساتھ آبجیکٹ کا موازنہ کیا جا رہا ہے)۔ اگر پہلی کار کی تیاری کا سال زیادہ ہے، تو طریقہ واپس آئے گا int > 0
۔ اس کا مطلب ہے کہ this car >
گاڑی o
۔ اس کے برعکس، اگر دوسری کار کی تیاری کا سال ( о
) زیادہ ہے، تو طریقہ ایک منفی نمبر لوٹائے گا، جس کا مطلب ہے کہ o > this
۔ آخر میں، اگر وہ برابر ہیں، تو طریقہ واپس آ جائے گا 0
. یہ سادہ طریقہ کار ہمارے لیے Car
اشیاء کے مجموعوں کو ترتیب دینے کے لیے پہلے ہی کافی ہے! آپ کو اور کچھ کرنے کی ضرورت نہیں ہے۔ اس کی جانچ پڑتال کر:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
// There was previously an error here
Collections.sort(cars);
System.out.println(cars);
}
}
کنسول آؤٹ پٹ:
[Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350},
Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290}]
کاروں کو ترتیب دیا گیا ہے جیسا کہ ہم چاہتے ہیں! :) 
Comparable
؟ مقابلے کے طریقہ کار کو Comparable
قدرتی ترتیب کہا جاتا ہے۔ اس کی وجہ یہ ہے کہ طریقہ کار میں compareTo()
آپ اس کلاس کی اشیاء کا موازنہ کرنے کا سب سے عام، یا قدرتی طریقہ بیان کرتے ہیں۔ جاوا میں پہلے سے ہی قدرتی ترتیب ہے۔ مثال کے طور پر، جاوا جانتا ہے کہ تاروں کو اکثر حروف تہجی کے حساب سے ترتیب دیا جاتا ہے، اور اعداد کو عددی قدر میں اضافہ کر کے۔ لہذا، اگر آپ sort()
نمبروں یا تاروں کی فہرست میں طریقہ کو کال کرتے ہیں، تو وہ ترتیب دی جائیں گی۔ Comparable<Car>
اگر ہمارا پروگرام عام طور پر تیاری کے سال کے لحاظ سے کاروں کا موازنہ اور ترتیب دیتا ہے، تو ہمیں انٹرفیس اور compareTo()
طریقہ کار کا استعمال کرتے ہوئے کاروں کے لیے قدرتی چھانٹی کی وضاحت کرنی چاہیے ۔ لیکن اگر یہ ہمارے لیے کافی نہیں ہے تو کیا ہوگا؟ آئیے تصور کریں کہ ہمارا پروگرام اتنا آسان نہیں ہے۔ زیادہ تر معاملات میں، کاروں کی قدرتی چھانٹی (جسے ہم نے تیاری کے سال کے لحاظ سے انجام دیا ہے) ہمارے لیے موزوں ہے۔ لیکن بعض اوقات ہمارے صارفین تیز رفتار ڈرائیونگ کے شوقین ہوتے ہیں۔ اگر ہم ان کے استعمال کے لیے کار کیٹلاگ تیار کر رہے ہیں، تو کاروں کو زیادہ سے زیادہ رفتار کے مطابق ترتیب دیا جانا چاہیے۔ 
Car
ہمارے لیے یہ واضح طور پر کافی نہیں ہے کہ ہم کلاس کی قدرتی ترتیب کو تیاری کے سال کے بجائے رفتار کے مطابق ترتیب دیں ۔ لیکن ہم اپنے 15% صارفین کو نظر انداز نہیں کر سکتے۔ تو ہم کیا کریں؟ ایک اور انٹرفیس یہاں ہماری مدد کے لیے آتا ہے: Comparator
. بالکل اسی طرح Comparable
، یہ ایک پیرامیٹرائزڈ انٹرفیس ہے۔ کیا فرق ہے؟ Comparable
ہماری اشیاء کو "مقابلہ" بناتا ہے اور ان کی سب سے قدرتی ترتیب ترتیب کی وضاحت کرتا ہے، یعنی وہ ترتیب جو زیادہ تر معاملات میں استعمال کیا جائے گا۔ Comparator
ایک الگ "موازنہ" انٹرفیس ہے۔ اگر ہمیں کسی قسم کے خصوصی ترتیب دینے کی ضرورت ہے، تو ہمیں Car
کلاس میں جانے اور کی منطق کو تبدیل کرنے کی ضرورت نہیں ہے compareTo()
۔ اس کے بجائے، ہم ایک الگ کلاس بنا سکتے ہیں جو Comparator کو لاگو کرتی ہے اور اسے سکھا سکتی ہے کہ ہمیں جس ترتیب کی ضرورت ہے اسے کیسے انجام دیا جائے!
import java.util.Comparator;
public class MaxSpeedCarComparator implements Comparator<Car> {
@Override
public int compare(Car o1, Car o2) {
return o1.getMaxSpeed() - o2.getMaxSpeed();
}
}
جیسا کہ آپ دیکھ سکتے ہیں، ہماری بات Comparator
بہت آسان ہے۔ ہمیں صرف ایک انٹرفیس طریقہ کو لاگو کرنے کی ضرورت ہے: compare()
. یہ دو Car
اشیاء کو ان پٹ کے طور پر لیتا ہے اور ان کی زیادہ سے زیادہ رفتار کا معمول کے انداز میں موازنہ کرتا ہے (تخفیف کے ذریعے)۔ جیسے compareTo()
، یہ ایک لوٹاتا ہے int
، اور موازنہ کا اصول ایک جیسا ہے۔ ہم اسے کیسے استعمال کرتے ہیں؟ یہ سب سیدھا ہے:
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class Main {
public static void main(String[] args) {
List<Car> cars = new ArrayList<>();
Car ferrari = new Car(1990, "Ferrari 360 Spider", 310);
Car lambo = new Car(2012, "Lamborghini Gallardo", 290);
Car bugatti = new Car(2010, "Bugatti Veyron", 350);
cars.add(ferrari);
cars.add(bugatti);
cars.add(lambo);
Comparator speedComparator = new MaxSpeedCarComparator();
Collections.sort(cars, speedComparator);
System.out.println(cars);
}
}
کنسول آؤٹ پٹ:
[Car{manufactureYear=2012, model='Lamborghini Gallardo', maxSpeed=290},
Car{manufactureYear=1990, model='Ferrari 360 Spider', maxSpeed=310},
Car{manufactureYear=2010, model='Bugatti Veyron', maxSpeed=350}]
ہم صرف ایک کمپیریٹر آبجیکٹ بناتے ہیں اور اسے Collections.sort()
ترتیب دینے والی فہرست کے ساتھ طریقہ کار میں بھیج دیتے ہیں۔ جب طریقہ ایک موازنہ حاصل کرتا ہے، تو یہ کلاس کے طریقہ کار sort()
میں بیان کردہ قدرتی ترتیب کو استعمال نہیں کرتا ہے ۔ اس کے بجائے، یہ اس کو بھیجے گئے موازنہ کنندہ کے ذریعہ بیان کردہ ترتیب دینے والے الگورتھم کو لاگو کرتا ہے۔ ایسا کرنے کے کیا فائدے ہیں؟ پہلے، موجودہ کوڈ کے ساتھ مطابقت۔ ہم نے ایک نیا، خصوصی چھانٹنے کا طریقہ بنایا ہے، موجودہ طریقہ کو برقرار رکھتے ہوئے جسے زیادہ تر وقت استعمال کیا جائے گا۔ ہم نے کلاس کو بالکل ہاتھ نہیں لگایا ۔ یہ ایک تھا ، اور اسی طرح یہ باقی ہے: Car
compareTo()
Car
Comparable
public class Car implements Comparable<Car> {
private int manufactureYear;
private String model;
private int maxSpeed;
public Car(int manufactureYear, String model, int maxSpeed) {
this.manufactureYear = manufactureYear;
this.model = model;
this.maxSpeed = maxSpeed;
}
@Override
public int compareTo(Car o) {
return this.getManufactureYear() - o.getManufactureYear();
}
// ...getters, setters, toString()
}
دوسرا، لچک. ہم جتنے چاہیں ترتیب دینے والے الگورتھم شامل کر سکتے ہیں۔ مثال کے طور پر، ہم کاروں کو رنگ، رفتار، وزن، یا بیٹ مین فلموں میں کار کو کتنی بار استعمال کیا گیا ہے کے لحاظ سے ترتیب دے سکتے ہیں۔ ہمیں صرف ایک اضافی تخلیق کرنے کی ضرورت ہے Comparator
۔ یہی ہے! آج آپ نے دو انتہائی اہم میکانزم کا مطالعہ کیا ہے جنہیں آپ اکثر کام پر حقیقی منصوبوں میں استعمال کریں گے۔ لیکن، جیسا کہ آپ جانتے ہیں، پریکٹس کے بغیر تھیوری کچھ بھی نہیں ہے۔ اب وقت آگیا ہے کہ آپ اپنے علم کو مضبوط کریں اور کچھ کام مکمل کریں!
GO TO FULL VERSION