కోడ్‌జిమ్/జావా బ్లాగ్/యాదృచ్ఛికంగా/జావా కంపారిటర్ ఇంటర్‌ఫేస్
John Squirrels
స్థాయి
San Francisco

జావా కంపారిటర్ ఇంటర్‌ఫేస్

సమూహంలో ప్రచురించబడింది
జావాలో కంపారేటర్లు మరియు పోలికల గురించి వ్రాయడానికి సోమరితనం మాత్రమే కాదు. నేను సోమరిని కాదు, కాబట్టి దయచేసి మరొక వివరణను ప్రేమించండి మరియు చింతించండి. ఇది నిరుపయోగంగా ఉండదని నేను ఆశిస్తున్నాను. మరియు అవును, ఈ వ్యాసం ప్రశ్నకు సమాధానం: " మీరు మెమరీ నుండి పోలికను వ్రాయగలరా? " ఈ కథనాన్ని చదివిన తర్వాత ప్రతి ఒక్కరూ మెమరీ నుండి పోలికను వ్రాయగలరని నేను ఆశిస్తున్నాను. జావాస్ కంపారిటర్ ఇంటర్‌ఫేస్ - 1

పరిచయం

మీకు తెలిసినట్లుగా, జావా అనేది ఆబ్జెక్ట్-ఓరియెంటెడ్ భాష. ఫలితంగా, జావాలో వస్తువులను మార్చడం ఆచారం. కానీ ముందుగానే లేదా తరువాత, మీరు కొన్ని లక్షణాల ఆధారంగా వస్తువులను పోల్చే పనిని ఎదుర్కొంటారు. ఉదాహరణకు : తరగతి ద్వారా వివరించబడిన కొన్ని సందేశాలు మనకు ఉన్నాయని అనుకుందాం Message:
public static class Message {
    private String message;
    private int id;

    public Message(String message) {
        this.message = message;
        this.id = new Random().nextInt(1000);
    }
    public String getMessage() {
        return message;
    }
    public Integer getId() {
        return id;
    }
    public String toString() {
        return "[" + id + "] " + message;
    }
}
ఈ తరగతిని ట్యుటోరియల్స్‌పాయింట్ జావా కంపైలర్‌లో ఉంచండి . దిగుమతి స్టేట్‌మెంట్‌లను కూడా జోడించడం మర్చిపోవద్దు:
import java.util.Random;
import java.util.ArrayList;
import java.util.List;
పద్ధతిలో main, అనేక సందేశాలను సృష్టించండి:
public static void main(String[] args){
    List<Message> messages = new ArrayList();
    messages.add(new Message("Hello, World!"));
    messages.add(new Message("Hello, Sun!"));
    System.out.println(messages);
}
మనం వాటిని పోల్చి చూడాలనుకుంటే మనం ఏమి చేస్తామో ఆలోచిద్దాం? ఉదాహరణకు, మేము id ద్వారా క్రమబద్ధీకరించాలనుకుంటున్నాము. మరియు ఒక క్రమాన్ని సృష్టించడానికి, ఏ వస్తువు మొదట రావాలి (అంటే చిన్నది) మరియు ఏది అనుసరించాలి (అంటే పెద్దది) అర్థం చేసుకోవడానికి మనం ఏదో ఒకవిధంగా వస్తువులను సరిపోల్చాలి. java.lang.Object వంటి తరగతితో ప్రారంభిద్దాం . అన్ని తరగతులు అంతర్లీనంగా తరగతిని వారసత్వంగా పొందుతాయని మాకు తెలుసు Object. మరియు ఇది అర్ధమే ఎందుకంటే ఇది "ప్రతిదీ ఒక వస్తువు" అనే భావనను ప్రతిబింబిస్తుంది మరియు అన్ని తరగతులకు సాధారణ ప్రవర్తనను అందిస్తుంది. ప్రతి తరగతికి రెండు పద్ధతులు ఉన్నాయని ఈ తరగతి నిర్దేశిస్తుంది: → hashCode పద్ధతి hashCodeకొంత సంఖ్యను అందిస్తుంది (int) వస్తువు యొక్క ప్రాతినిధ్యం. అంటే ఏమిటి? మీరు తరగతికి సంబంధించిన రెండు వేర్వేరు సందర్భాలను సృష్టించినట్లయితే, అవి వేర్వేరు hashCodesని కలిగి ఉండాలి. పద్ధతి యొక్క వివరణ చాలా చెబుతుంది: "సహేతుకంగా ఆచరణాత్మకమైనది, క్లాస్ ఆబ్జెక్ట్ ద్వారా నిర్వచించబడిన హాష్‌కోడ్ పద్ధతి విభిన్న వస్తువులకు విభిన్న పూర్ణాంకాలను అందిస్తుంది". మరో మాటలో చెప్పాలంటే, రెండు వేర్వేరు instances కోసం, వేర్వేరు s ఉండాలి hashCode. అంటే, ఈ పద్ధతి మన పోలికకు తగినది కాదు. → equals_ పద్ధతి equalsప్రశ్నకు సమాధానమిస్తుంది "ఈ వస్తువులు సమానంగా ఉన్నాయా?" మరియు a boolean." డిఫాల్ట్‌గా, ఈ పద్ధతి క్రింది కోడ్‌ని కలిగి ఉంటుంది:
public boolean equals(Object obj) {
    return (this == obj);
}
అంటే, ఈ పద్ధతిని భర్తీ చేయకపోతే, ఆబ్జెక్ట్ రిఫరెన్స్‌లు సరిపోతాయా లేదా అనేది తప్పనిసరిగా చెబుతుంది. ఇది మా సందేశాల కోసం మేము కోరుకునేది కాదు, ఎందుకంటే మేము సందేశ ఐడిలపై ఆసక్తి కలిగి ఉన్నాము, ఆబ్జెక్ట్ రిఫరెన్స్‌లపై కాదు. మరియు మేము పద్ధతిని భర్తీ చేసినప్పటికీ equals, అవి సమానంగా ఉన్నాయో లేదో తెలుసుకోవడానికి మనం ఎక్కువగా ఆశించవచ్చు. మరియు ఆర్డర్‌ని నిర్ణయించడానికి ఇది సరిపోదు. కాబట్టి మనకు ఏమి కావాలి? పోల్చిచూసేది మనకు అవసరం. పోల్చి చూసేవాడు ఒక Comparator. జావా APIని తెరిచి , కంపారిటర్‌ని కనుగొనండి . java.util.Comparatorనిజానికి, ఒక ఇంటర్ఫేస్ ఉందిjava.util.Comparator and java.util.Comparable మీరు గమనిస్తే, అటువంటి ఇంటర్ఫేస్ ఉంది. దీన్ని అమలు చేసే ఒక తరగతి, "నేను వస్తువులను పోల్చే పద్ధతిని అమలు చేస్తున్నాను" అని చెబుతుంది. మీరు నిజంగా గుర్తుంచుకోవలసిన ఏకైక విషయం కంపారిటర్ ఒప్పందం, ఇది క్రింది విధంగా వ్యక్తీకరించబడింది:
Comparator returns an int according to the following rules:

It returns a negative int if the first object is smaller
It returns a positive int if the first object is larger
It returns zero if the objects are equal
ఇప్పుడు కంపారిటర్ రాద్దాం. మేము దిగుమతి చేసుకోవాలి java.util.Comparator. దిగుమతి ప్రకటన తర్వాత, ఈ mainపద్ధతికి క్రింది వాటిని జోడించండి: Comparator<Message> comparator = new Comparator<Message>(); వాస్తవానికి, ఇది పని చేయదు, ఎందుకంటే Comparatorఇది ఇంటర్‌ఫేస్. {}కాబట్టి మేము కుండలీకరణాల తర్వాత కర్లీ జంట కలుపులను జోడిస్తాము . కలుపుల లోపల క్రింది పద్ధతిని వ్రాయండి:
public int compare(Message o1, Message o2) {
    return o1.getId().compareTo(o2.getId());
}
మీరు అక్షరక్రమాన్ని కూడా గుర్తుంచుకోవలసిన అవసరం లేదు. కంపారిజన్ అంటే పోలిక చేసేవాడు, అంటే పోల్చాడు. వస్తువుల సాపేక్ష క్రమాన్ని సూచించడానికి, మేము ఒక int. ప్రాథమికంగా అంతే. బాగుంది మరియు సులభం. మీరు ఉదాహరణ నుండి చూడగలిగినట్లుగా, కంపారేటర్‌తో పాటు, మరొక ఇంటర్‌ఫేస్ ఉంది — java.lang.Comparable, ఇది మేము పద్ధతిని అమలు చేయవలసి ఉంటుంది compareTo. ఈ ఇంటర్‌ఫేస్ ఇలా చెబుతోంది, "నన్ను అమలు చేసే తరగతి క్లాస్ యొక్క ఉదాహరణలను సరిపోల్చడం సాధ్యం చేస్తుంది." ఉదాహరణకు, To Integerయొక్క అమలు compareక్రింది విధంగా ఉంది:
(x < y) ? -1 : ((x == y) ? 0 : 1)
జావా 8 కొన్ని మంచి మార్పులను ప్రవేశపెట్టింది. మీరు ఇంటర్‌ఫేస్‌ని నిశితంగా పరిశీలిస్తే Comparator, దాని పైన ఉన్న ఉల్లేఖనాన్ని మీరు చూస్తారు @FunctionalInterface. ఈ ఉల్లేఖనం సమాచార ప్రయోజనాల కోసం మరియు ఈ ఇంటర్‌ఫేస్ ఫంక్షనల్‌గా ఉందని మాకు తెలియజేస్తుంది. దీనర్థం ఈ ఇంటర్‌ఫేస్‌లో 1 అబ్‌స్ట్రాక్ట్ పద్ధతి మాత్రమే ఉంది, ఇది అమలు లేని పద్ధతి. ఇది మనకు ఏమి ఇస్తుంది? ఇప్పుడు మనం కంపారిటర్ కోడ్‌ని ఇలా వ్రాయవచ్చు:
Comparator<Message> comparator = (o1, o2) -> o1.getId().compareTo(o2.getId());
మేము కుండలీకరణాల్లో వేరియబుల్స్ పేరు పెడతాము. ఒకే ఒక పద్ధతి ఉన్నందున, అవసరమైన సంఖ్య మరియు ఇన్‌పుట్ పారామితుల రకాలు స్పష్టంగా ఉన్నాయని జావా చూస్తుంది. అప్పుడు మేము వాటిని కోడ్‌లోని ఈ భాగానికి పంపడానికి బాణం ఆపరేటర్‌ని ఉపయోగిస్తాము. ఇంకా ఏమిటంటే, జావా 8కి ధన్యవాదాలు, ఇప్పుడు మనకు ఇంటర్‌ఫేస్‌లలో డిఫాల్ట్ పద్ధతులు ఉన్నాయి. మేము ఇంటర్‌ఫేస్‌ను అమలు చేసినప్పుడు ఈ పద్ధతులు డిఫాల్ట్‌గా కనిపిస్తాయి. ఇంటర్‌ఫేస్‌లో Comparatorఅనేకం ఉన్నాయి. ఉదాహరణకి:
Comparator moreImportant = Comparator.reverseOrder();
Comparator lessImportant = Comparator.naturalOrder();
మీ కోడ్‌ను క్లీనర్‌గా మార్చే మరో పద్ధతి ఉంది. పైన ఉన్న ఉదాహరణను పరిశీలించండి, ఇక్కడ మేము మా కంపారిటర్‌ను నిర్వచించాము. ఇది ఏమి చేస్తుంది? ఇది చాలా ప్రాచీనమైనది. ఇది కేవలం ఒక వస్తువును తీసుకుంటుంది మరియు "పోల్చదగిన" కొంత విలువను సంగ్రహిస్తుంది. ఉదాహరణకు, Integerఇంప్లిమెంట్‌లు comparable, కాబట్టి మేము మెసేజ్ ఐడి ఫీల్డ్‌ల విలువలపై compareTo ఆపరేషన్ చేయగలుగుతాము. ఈ సాధారణ కంపారిటర్ ఫంక్షన్ ఇలా వ్రాయవచ్చు:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
మరో మాటలో చెప్పాలంటే, మనకు Comparatorఇలాంటి పోలిక ఉంది: ఇది వస్తువులను తీసుకుంటుంది, వాటి నుండి getId()ఒకదాన్ని పొందడానికి పద్ధతిని ఉపయోగిస్తుంది Comparable, ఆపై compareToపోల్చడానికి ఉపయోగిస్తుంది. మరియు అంతకన్నా భయంకరమైన నిర్మాణాలు లేవు. చివరగా, నేను మరొక లక్షణాన్ని గమనించాలనుకుంటున్నాను. పోలికలను బంధించవచ్చు. ఉదాహరణకి:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
comparator = comparator.thenComparing(obj -> obj.getMessage().length());

అప్లికేషన్

కంపారిటర్‌ను ప్రకటించడం చాలా తార్కికంగా మారుతుంది, మీరు అనుకోలేదా? ఇప్పుడు దీన్ని ఎలా, ఎక్కడ ఉపయోగించాలో చూడాలి. → Collections.sort(java.util.Collections) మేము సేకరణలను ఈ విధంగా క్రమబద్ధీకరించవచ్చు. కానీ ప్రతి సేకరణ కాదు, జాబితాలు మాత్రమే. ఇక్కడ అసాధారణంగా ఏమీ లేదు, ఎందుకంటే జాబితాలు మీరు ఎలిమెంట్‌లను వాటి సూచిక ద్వారా యాక్సెస్ చేసే రకమైన సేకరణలు. ఇది రెండవ మూలకాన్ని మూడవ మూలకంతో మార్చుకోవడానికి అనుమతిస్తుంది. అందుకే క్రింది క్రమబద్ధీకరణ పద్ధతి జాబితాల కోసం మాత్రమే:
Comparator<Message> comparator = Comparator.comparing(obj -> obj.getId());
Collections.sort(messages, comparator);
Arrays.sort(java.util.Arrays) శ్రేణులను క్రమబద్ధీకరించడం కూడా సులభం. మళ్ళీ, అదే కారణంతో - వాటి మూలకాలు ఇండెక్స్ ద్వారా యాక్సెస్ చేయబడతాయి. → Descendants of java.util.SortedSet and java.util.SortedMap మీరు దానిని గుర్తుకు తెచ్చుకుంటారు Setమరియు Mapమూలకాలు నిల్వ చేయబడిన క్రమంలో హామీ ఇవ్వరు. కానీ, ఆర్డర్‌కు హామీ ఇచ్చే ప్రత్యేక అమలులు మా వద్ద ఉన్నాయి. మరియు సేకరణ మూలకాలు అమలు చేయకుంటే , మేము దాని కన్స్ట్రక్టర్‌కు java.util.Comparableaని పంపవచ్చు :Comparator
Set<Message> msgSet = new TreeSet(comparator);
Stream API జావా 8లో కనిపించిన స్ట్రీమ్ APIలో, కంపారిటర్‌లు స్ట్రీమ్ ఎలిమెంట్‌లతో పనిని సులభతరం చేయడానికి మిమ్మల్ని అనుమతిస్తారు. ఉదాహరణకు, మనకు 0 నుండి 999 వరకు ఉన్న యాదృచ్ఛిక సంఖ్యల శ్రేణి అవసరమని అనుకుందాం:
Supplier<Integer> randomizer = () -> new Random().nextInt(1000);
Stream.generate(randomizer)
    .limit(10)
    .sorted(Comparator.naturalOrder())
    .forEach(e -> System.out.println(e));
మేము ఇక్కడ ఆగిపోవచ్చు, కానీ ఇంకా ఆసక్తికరమైన సమస్యలు ఉన్నాయి. ఉదాహరణకు, మీరు Mapఒక మెసేజ్ ఐడిని సిద్ధం చేయాలని అనుకుందాం. అదనంగా, మేము ఈ కీలను క్రమబద్ధీకరించాలనుకుంటున్నాము, కాబట్టి మేము క్రింది కోడ్‌తో ప్రారంభిస్తాము:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg));
మేము నిజానికి ఇక్కడ పొందండి HashMap. మరియు మనకు తెలిసినట్లుగా, ఇది ఏ ఆర్డర్‌కు హామీ ఇవ్వదు. ఫలితంగా, id ద్వారా క్రమబద్ధీకరించబడిన మా మూలకాలు వాటి క్రమాన్ని కోల్పోతాయి. మంచిది కాదు. మేము మా కలెక్టర్‌ని కొంచెం మార్చాలి:
Map<Integer, Message> collected = Arrays.stream(messages)
                .sorted(Comparator.comparing(msg -> msg.getId()))
                .collect(Collectors.toMap(msg -> msg.getId(), msg -> msg, (oldValue, newValue) -> oldValue, TreeMap::new));
కోడ్ కొంచెం భయంకరంగా కనిపించడం ప్రారంభించింది, కానీ ఇప్పుడు సమస్య సరిగ్గా పరిష్కరించబడింది. వివిధ సమూహాల గురించి ఇక్కడ మరింత చదవండి: మీరు మీ స్వంత కలెక్టర్‌ని సృష్టించవచ్చు. ఇక్కడ మరింత చదవండి: "Java 8లో కస్టమ్ కలెక్టర్‌ని సృష్టిస్తోంది" . మరియు మీరు ఇక్కడ చర్చను చదవడం ద్వారా ప్రయోజనం పొందుతారు: "ప్రవాహంతో మ్యాప్ చేయడానికి జావా 8 జాబితా" .

పతనం-ఉచ్చు

Comparatorమరియు Comparableమంచివి. కానీ మీరు గుర్తుంచుకోవలసిన ఒక స్వల్పభేదాన్ని ఉంది. ఒక తరగతి సార్టింగ్ చేసినప్పుడు, అది మీ తరగతిని aకి మార్చవచ్చని ఆశిస్తుంది Comparable. ఇది కాకపోతే, మీరు రన్ టైమ్‌లో ఎర్రర్‌ను అందుకుంటారు. ఒక ఉదాహరణ చూద్దాం:
SortedSet<Message> msg = new TreeSet<>();
msg.add(new Message(2, "Developer".getBytes()));
ఇక్కడ తప్పేమీ లేదనిపిస్తోంది. కానీ నిజానికి, మా ఉదాహరణలో, ఇది ఒక లోపంతో విఫలమవుతుంది: java.lang.ClassCastException: Message cannot be cast to java.lang.Comparable మరియు అన్నీ ఎందుకంటే ఇది మూలకాలను క్రమబద్ధీకరించడానికి ప్రయత్నించింది (ఇది ఒక SortedSet, అన్ని తరువాత)...కానీ సాధ్యం కాలేదు. SortedMapమరియు తో పని చేస్తున్నప్పుడు దీన్ని మర్చిపోవద్దు SortedSet.
వ్యాఖ్యలు
  • జనాదరణ పొందినది
  • కొత్తది
  • పాతది
వ్యాఖ్యానించడానికి మీరు తప్పనిసరిగా సైన్ ఇన్ చేసి ఉండాలి
ఈ పేజీకి ఇంకా ఎలాంటి వ్యాఖ్యలు లేవు