एक जावा वर्ग को तुलनीय क्यों लागू करना चाहिए?


136

जावा का Comparableउपयोग क्यों किया जाता है? कोई Comparableवर्ग में क्यों लागू करेगा ? एक वास्तविक जीवन उदाहरण क्या है जहां आपको तुलनीय लागू करने की आवश्यकता है?



यहाँ एक अच्छा उदाहरण है: java67.blogspot.com/2012/10/…
james.garriss

जवाबों:


212

यहाँ एक वास्तविक जीवन नमूना है। ध्यान दें कि Stringयह भी लागू करता है Comparable

class Author implements Comparable<Author>{
    String firstName;
    String lastName;

    @Override
    public int compareTo(Author other){
        // compareTo should return < 0 if this is supposed to be
        // less than other, > 0 if this is supposed to be greater than 
        // other and 0 if they are supposed to be equal
        int last = this.lastName.compareTo(other.lastName);
        return last == 0 ? this.firstName.compareTo(other.firstName) : last;
    }
}

बाद में..

/**
 * List the authors. Sort them by name so it will look good.
 */
public List<Author> listAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    Collections.sort(authors);
    return authors;
}

/**
 * List unique authors. Sort them by name so it will look good.
 */
public SortedSet<Author> listUniqueAuthors(){
    List<Author> authors = readAuthorsFromFileOrSomething();
    return new TreeSet<Author>(authors);
}

15
मैं सिर्फ यह नोट करना चाहता हूं कि अक्सर आप अपनी विधि के अनुरूप होना चाहते हैं equals(और इसलिए hashCode) ओवरराइड करना चाहते हैं compareTo। उदाहरण के लिए, यह आवश्यक है यदि आप चाहते हैं कि वर्ग ए के साथ अच्छा खेले TreeSet
6

बस वापस क्यों नहीं last?
अनिर्बान नाग 'टिनटिनम'

@ AnirbanNag'tintinmj 'पहले नाम से स्वचालित रूप से सॉर्ट करने के लिए कि अंतिम नाम समान है।
OddDev

प्लस की एक अच्छी व्याख्या के लिए क्यों तुलना एक इंट और इसका क्या मतलब है। सबसे उपयोगी।
james.garriss

1
@ user3932000: ठीक है, यह सभी इंटरफेस का बिंदु है। लेकिन ध्यान दें कि "अन्य जावा तरीके" में उपयोगकर्ता द्वारा लिखित तरीके शामिल हैं! वास्तव में, मैं दावा करूंगा कि अधिकांश उपयोगकर्ता उपयोगकर्ता के कोड का उपयोग करते हैं। बड़े कोड आधारों में, "अपने आप" जल्दी से "अन्य" बन जाता है
एन्नो शियोजी

40

तुलनीय एक प्राकृतिक आदेश को परिभाषित करता है। इसका मतलब यह है कि आप इसे परिभाषित कर रहे हैं जब एक वस्तु को "कम से कम" या "से अधिक" माना जाना चाहिए।

मान लीजिए कि आपके पास पूर्णांकों का एक गुच्छा है और आप उन्हें क्रमबद्ध करना चाहते हैं। यह बहुत आसान है, बस उन्हें एक सॉर्ट किए गए संग्रह में डाल दें, है ना?

TreeSet<Integer> m = new TreeSet<Integer>(); 
m.add(1);
m.add(3);
m.add(2);
for (Integer i : m)
... // values will be sorted

लेकिन अब मान लीजिए कि मेरे पास कुछ कस्टम ऑब्जेक्ट है, जहां सॉर्टिंग मेरे लिए समझ में आता है, लेकिन अपरिभाषित है। मान लीजिए, मेरे पास जनसंख्या घनत्व वाले ज़िपकोड द्वारा जिलों का प्रतिनिधित्व करने वाला डेटा है, और मैं उन्हें घनत्व द्वारा क्रमबद्ध करना चाहता हूं:

public class District {
  String zipcode; 
  Double populationDensity;
}

अब उन्हें क्रमबद्ध करने का सबसे आसान तरीका यह है कि उन्हें तुलनात्मक रूप से लागू करके एक प्राकृतिक आदेश के साथ परिभाषित किया जाए, जिसका अर्थ है कि इन वस्तुओं को ऑर्डर करने के लिए एक मानक तरीका निर्धारित किया गया है:

public class District implements Comparable<District>{
  String zipcode; 
  Double populationDensity;
  public int compareTo(District other)
  {
    return populationDensity.compareTo(other.populationDensity);
  }
}

ध्यान दें कि आप एक तुलनित्र को परिभाषित करके बराबर काम कर सकते हैं। अंतर यह है कि तुलनित्र वस्तु के बाहर आदेश देने वाले तर्क को परिभाषित करता है । शायद एक अलग प्रक्रिया में मुझे समान वस्तुओं को zipcode द्वारा ऑर्डर करने की आवश्यकता होती है - उस स्थिति में ऑर्डर करना आवश्यक रूप से ऑब्जेक्ट की संपत्ति नहीं है, या ऑब्जेक्ट प्राकृतिक ऑर्डरिंग से अलग है। आप पूर्णांक पर कस्टम ऑर्डर को परिभाषित करने के लिए एक बाहरी तुलनित्र का उपयोग कर सकते हैं, उदाहरण के लिए उन्हें उनके वर्णानुक्रम मूल्य द्वारा क्रमबद्ध करके।

मूल रूप से आदेश देने वाला तर्क कहीं न कहीं मौजूद है। यह हो सकता है -

  • ऑब्जेक्ट में ही, अगर यह स्वाभाविक रूप से तुलनीय है (तुलना-पूर्ण पूर्णांक को बढ़ाता है)

  • एक बाहरी तुलनित्र में आपूर्ति की, ऊपर के उदाहरण में।


अच्छा उदाहरण है, लेकिन इसके TreeSet<Integer>बजाय होना चाहिए TreeMap<Integer>, क्योंकि उत्तरार्द्ध मौजूद नहीं है, ट्रीमैप हमेशा <Key,Value>-पेयर होते हैं । Btw, एक काल्पनिक TreeMap<District, Object>ही काम करेगा, अगर जिला तुलनात्मक रूप से लागू हो, है ना? फिर भी इसे समझने की कोशिश कर रहे हैं
फिल्प ४

14

जावदोक से उद्धृत;

यह इंटरफ़ेस प्रत्येक वर्ग की वस्तुओं पर कुल आदेश देता है जो इसे लागू करता है। इस ऑर्डर को क्लास के नेचुरल ऑर्डरिंग के रूप में संदर्भित किया जाता है, और क्लास की तुलना विधि को इसकी प्राकृतिक तुलना विधि के रूप में संदर्भित किया जाता है।

इस इंटरफ़ेस को लागू करने वाली वस्तुओं की सूचियाँ (और सरणियाँ) कलेक्शन.सोर्ट (और एरेस.ओर्ट) द्वारा स्वचालित रूप से सॉर्ट की जा सकती हैं। इस इंटरफ़ेस को लागू करने वाली वस्तुओं का उपयोग किसी सॉर्ट किए गए नक्शे में या एक सॉर्ट किए गए सेट में तत्वों के रूप में किया जा सकता है, एक तुलनित्र निर्दिष्ट करने की आवश्यकता के बिना।

संपादित करें: .. और महत्वपूर्ण बिट को बोल्ड बनाया।


4
मैं कहूंगा कि आपके द्वारा बोल्ड किए गए वाक्य के बाद बस (यदि अधिक नहीं) महत्वपूर्ण है।
माइकल बोर्गवर्ड

8

तथ्य यह है कि एक वर्ग का Comparableमतलब है कि आप उस वर्ग से दो ऑब्जेक्ट ले सकते हैं और उनकी तुलना कर सकते हैं। कुछ कक्षाएं, जैसे कि कुछ संग्रह (एक संग्रह में सॉर्ट फ़ंक्शन) जो वस्तुओं को क्रम में रखते हैं, उन पर तुलनीय होने के लिए भरोसा करते हैं (क्रमबद्ध करने के लिए आपको यह जानने की आवश्यकता है कि कौन सी वस्तु "सबसे बड़ी" है और आगे है)।


8

ऊपर दिए गए अधिकांश उदाहरण दिखाते हैं कि कैसे एक मौजूदा तुलनीय वस्तु का पुन: उपयोग करना है। यदि आप एक ही वर्ग की दो वस्तुओं की तुलना करना चाहते हैं, तो आप अपनी खुद की तुलना को लागू करना चाहेंगे, एक एयरलाइनलाइन ऑब्जेक्ट का कहना है कि आप मूल्य के आधार पर छांटना चाहेंगे (कम पहले स्थान पर है), इसके बाद स्टॉपओवर की संख्या (फिर से, कम है) पहले स्थान पर), आप निम्न कार्य करेंगे:

class AirlineTicket implements Comparable<Cost>
{
    public double cost;
    public int stopovers;
    public AirlineTicket(double cost, int stopovers)
    {
        this.cost = cost; this.stopovers = stopovers ;
    }

    public int compareTo(Cost o)
    {
        if(this.cost != o.cost)
          return Double.compare(this.cost, o.cost); //sorting in ascending order. 
        if(this.stopovers != o.stopovers)
          return this.stopovers - o.stopovers; //again, ascending but swap the two if you want descending
        return 0;            
    }
}

6

कई क्षेत्रों की तुलना को लागू करने का एक आसान तरीका है अमरूद की तुलना - इसके बाद आप कह सकते हैं

   public int compareTo(Foo that) {
     return ComparisonChain.start()
         .compare(lastName, that.lastName)
         .compare(firstName, that.firstName)
         .compare(zipCode, that.zipCode)
         .result();
   }

के बजाय

  public int compareTo(Person other) {
    int cmp = lastName.compareTo(other.lastName);
    if (cmp != 0) {
      return cmp;
    }
    cmp = firstName.compareTo(other.firstName);
    if (cmp != 0) {
      return cmp;
    }
    return Integer.compare(zipCode, other.zipCode);
  }
}

3

उदाहरण के लिए, जब आप एक सॉर्ट किया गया संग्रह या नक्शा चाहते हैं


फर्नांडो का मतलब क्या है: यदि आप "चीजों" को स्टोर करते हैं जो एक सॉर्ट किए गए कंटेनर वर्ग में तुलनीय लागू करते हैं, तो सॉर्ट किए गए कंटेनर वर्ग स्वचालित रूप से उन "चीजों" का आदेश दे सकते हैं।
इयान दुर्कन

2

तुलनीय का उपयोग आपकी कक्षा के उदाहरणों की तुलना करने के लिए किया जाता है। हम कई तरीकों से उदाहरणों की तुलना कर सकते हैं यही कारण है कि हमें यह जानने के लिए एक विधि को लागू करने की आवश्यकता compareToहै कि कैसे (विशेषताएँ) हम उदाहरणों की तुलना करना चाहते हैं।

Dog वर्ग:

package test;
import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

Main वर्ग:

package test;

import java.util.Arrays;

public class Main {

    public static void main(String[] args) {
        Dog d1 = new Dog("brutus");
        Dog d2 = new Dog("medor");
        Dog d3 = new Dog("ara");
        Dog[] dogs = new Dog[3];
        dogs[0] = d1;
        dogs[1] = d2;
        dogs[2] = d3;

        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * brutus
         * medor
         * ara
         */

        Arrays.sort(dogs, Dog.NameComparator);
        for (int i = 0; i < 3; i++) {
            System.out.println(dogs[i].getName());
        }
        /**
         * Output:
         * ara
         * medor
         * brutus
         */

    }
}

यहाँ जावा में तुलनीय का उपयोग करने का एक अच्छा उदाहरण दिया गया है:

http://www.onjava.com/pub/a/onjava/2003/03/12/java_comp.html?page=2


2

जब आप Comparableइंटरफ़ेस लागू करते हैं , तो आपको विधि लागू करने की आवश्यकता होती है compareTo()। आपको वस्तुओं की तुलना करने के लिए इसकी आवश्यकता है, उदाहरण के लिए, ArrayListकक्षा की छँटाई विधि । आपको अपनी वस्तुओं की तुलना करने के लिए एक तरीका चाहिए जो उन्हें क्रमबद्ध करने में सक्षम हो। तो आपको compareTo()अपनी कक्षा में एक कस्टम विधि की आवश्यकता है ताकि आप इसे ArrayListसॉर्ट विधि के साथ उपयोग कर सकें । compareTo()विधि रिटर्न -1,0,1।

मैंने अभी जावा हेड 2.0 में एक अध्याय के अनुसार पढ़ा है, मैं अभी भी सीख रहा हूं।


1

ठीक है, लेकिन compareTo()तुलनात्मक इंटरफ़ेस को लागू किए बिना सिर्फ एक विधि को क्यों नहीं परिभाषित किया जाए। उदाहरण के लिए एक वर्ग Cityद्वारा परिभाषित किया गया है अपने nameऔर temperatureऔर

public int compareTo(City theOther)
{
    if (this.temperature < theOther.temperature)
        return -1;
    else if (this.temperature > theOther.temperature)
        return 1;
    else
        return 0;
}

यह काम नहीं करता। तुलनीय को लागू किए बिना - मुझे क्लासकास्ट अपवाद मिलता है
करण आहूजा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.