हाय! आज आपण वस्तूंची तुलना करण्याबद्दल बोलणार आहोत. हम्म... पण आपण या विषयावर एकापेक्षा जास्त वेळा बोललो नाही का? :/
==
ऑपरेटर कसे कार्य करते, तसेच पद्धती 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);
}
}
आणि खरंच, तुम्ही लिहिलेल्या वर्गांच्या वस्तूंची क्रमवारी कशी लावायची हे भाषेला कसे कळेल? आपल्या प्रोग्रामला काय करण्याची आवश्यकता आहे यावर हे अवलंबून आहे. या वस्तूंची तुलना करण्यासाठी आपण जावाला शिकवले पाहिजे. आणि आपल्याला पाहिजे तशी तुलना करणे. Java मध्ये यासाठी एक विशेष यंत्रणा आहे: इंटरफेस 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()
, आम्ही कारची तुलना करण्यासाठी आमचे तर्क लागू करतो. समजा, आम्हाला उत्पादनाच्या वर्षानुसार त्यांची क्रमवारी लावायची आहे. तुम्हाला कदाचित लक्षात आले असेल की ही पद्धत एक नाही, a compareTo()
मिळवते . हे तुम्हाला आश्चर्यचकित करू देऊ नका. जेव्हा आपण दोन वस्तूंची तुलना करतो, तेव्हा 3 शक्यता असतात: int
boolean
а < 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()
तुम्ही या वर्गातील वस्तूंची तुलना करण्याचा सर्वात सामान्य किंवा नैसर्गिक मार्ग परिभाषित करता. Java मध्ये आधीपासूनच नैसर्गिक क्रम आहे. उदाहरणार्थ, Java ला माहित आहे की स्ट्रिंग्स बहुतेक वेळा अक्षरानुसार क्रमवारी लावल्या जातात आणि संख्यात्मक मूल्य वाढवून संख्या. म्हणून, जर तुम्ही 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()
, ते an परत करते 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
. बस एवढेच! आज तुम्ही दोन अतिशय महत्त्वाच्या यंत्रणांचा अभ्यास केला आहे ज्याचा वापर तुम्ही कामाच्या ठिकाणी प्रत्यक्ष प्रकल्पांमध्ये कराल. परंतु, तुम्हाला माहिती आहे, सरावशिवाय सिद्धांत काहीच नाही. आता आपले ज्ञान एकत्रित करण्याची आणि काही कार्ये पूर्ण करण्याची वेळ आली आहे!