ওহে! আজ আমরা বস্তুর তুলনা সম্পর্কে কথা বলতে যাচ্ছি। হুম... কিন্তু আমরা কি এই বিষয়ে একাধিকবার কথা বলিনি? :/ আমরা জানি কিভাবে
==
অপারেটর কাজ করে, সেইসাথে 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
, একটি নয় 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()
পদ্ধতি কিন্তু এটা যদি আমাদের জন্য যথেষ্ট না হয়? আসুন কল্পনা করি যে আমাদের প্রোগ্রামটি এত সহজ নয়। বেশিরভাগ ক্ষেত্রে, গাড়ির প্রাকৃতিক বাছাই (যা আমরা উত্পাদনের বছর অনুসারে সম্পাদন করতে সেট করেছি) আমাদের জন্য উপযুক্ত। কিন্তু কখনও কখনও আমাদের গ্রাহকরা দ্রুত গাড়ি চালানোর অনুরাগী। যদি আমরা তাদের জন্য একটি গাড়ী ক্যাটালগ প্রস্তুত করছি যাতে তারা অনুধাবন করতে পারে, গাড়িগুলিকে সর্বোচ্চ গতির দ্বারা বাছাই করা উচিত। উদাহরণস্বরূপ, ধরুন আমাদের এইভাবে 15% সময় সাজাতে হবে। Car
ক্লাসের প্রাকৃতিক বাছাইটি উত্পাদনের বছরের পরিবর্তে গতি অনুসারে সেট করার জন্য এটি স্পষ্টতই যথেষ্ট নয় । কিন্তু আমরা আমাদের 15% গ্রাহককে উপেক্ষা করতে পারি না। তাই আমরা কি কাজ করতে পারি? আরেকটি ইন্টারফেস এখানে আমাদের সাহায্যে আসে: Comparator
. ঠিক যেমন Comparable
, এটি একটি প্যারামিটারাইজড ইন্টারফেস। পার্থক্য কি? Comparable
আমাদের অবজেক্টগুলিকে "তুলনাযোগ্য" করে তোলে এবং তাদের সবচেয়ে প্রাকৃতিক সাজানোর ক্রমকে সংজ্ঞায়িত করে, অর্থাৎ সাজানোর ক্রম যা বেশিরভাগ ক্ষেত্রে ব্যবহার করা হবে। Comparator
একটি পৃথক "তুলনা" ইন্টারফেস। আমাদের যদি কোনো ধরনের বিশেষ বাছাই ক্রম বাস্তবায়ন করতে হয়, আমাদের ক্লাসে গিয়ে Car
এর যুক্তি পরিবর্তন করতে হবে না compareTo()
। পরিবর্তে, আমরা একটি পৃথক ক্লাস তৈরি করতে পারি যা তুলনাকারীকে প্রয়োগ করে এবং আমাদের প্রয়োজনীয় বাছাইটি কীভাবে সম্পাদন করতে হয় তা শেখাতে পারি!
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