CodeGym /Java Blog /சீரற்ற /சம மற்றும் ஹாஷ்கோட் முறைகள்: சிறந்த நடைமுறைகள்
John Squirrels
நிலை 41
San Francisco

சம மற்றும் ஹாஷ்கோட் முறைகள்: சிறந்த நடைமுறைகள்

சீரற்ற குழுவில் வெளியிடப்பட்டது
வணக்கம்! இன்று நாம் ஜாவாவில் இரண்டு முக்கியமான முறைகளைப் பற்றி பேசுவோம்: equals()மற்றும் hashCode(). நாங்கள் அவர்களைச் சந்திப்பது இது முதல் முறையல்ல: கோட்ஜிம் பாடத்திட்டம் பற்றி ஒரு சிறிய பாடத்துடன்equals() தொடங்குகிறது — நீங்கள் அதை மறந்துவிட்டாலோ அல்லது இதுவரை பார்க்காமல் இருந்தாலோ அதைப் படிக்கவும்... சம மற்றும் ஹாஷ்கோட் முறைகள்: சிறந்த நடைமுறைகள் - 1இன்றைய பாடத்தில், அதைப் பற்றி பேசுவோம். இந்த கருத்துக்கள் விரிவாக. என்னை நம்புங்கள், நாங்கள் பேசுவதற்கு ஏதாவது இருக்கிறது! ஆனால் நாம் புதியதுக்குச் செல்வதற்கு முன், நாங்கள் ஏற்கனவே உள்ளடக்கியதைப் புதுப்பிப்போம் :) நீங்கள் நினைவில் வைத்துள்ளபடி, ஆபரேட்டரைப் பயன்படுத்தி இரண்டு பொருட்களை ஒப்பிடுவது பொதுவாக தவறான யோசனையாகும் ==, ஏனெனில் ==குறிப்புகளை ஒப்பிடுகிறது. சமீபத்திய பாடத்திலிருந்து கார்கள் பற்றிய எங்களின் உதாரணம் இங்கே:

public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
கன்சோல் வெளியீடு:

false
ஒரே மாதிரியான இரண்டு பொருட்களை நாங்கள் உருவாக்கியதாகத் தெரிகிறது Car: இரண்டு கார் பொருள்களின் தொடர்புடைய புலங்களின் மதிப்புகள் ஒரே மாதிரியாக இருக்கும், ஆனால் ஒப்பீட்டின் முடிவு இன்னும் தவறானது. காரணத்தை நாங்கள் ஏற்கனவே அறிவோம்: car1மற்றும் car2குறிப்புகள் வெவ்வேறு நினைவக முகவரிகளை சுட்டிக்காட்டுகின்றன, எனவே அவை சமமாக இல்லை. ஆனால் நாம் இன்னும் இரண்டு பொருள்களை ஒப்பிட விரும்புகிறோம், இரண்டு குறிப்புகள் அல்ல. பொருட்களை ஒப்பிடுவதற்கான சிறந்த தீர்வு முறை equals().

சமம்() முறை

இந்த முறையை நாங்கள் புதிதாக உருவாக்கவில்லை என்பதை நீங்கள் நினைவில் கொள்ளலாம், மாறாக நாங்கள் அதை மீறுகிறோம்: இந்த equals()முறை வகுப்பில் வரையறுக்கப்பட்டுள்ளது Object. அதன் வழக்கமான வடிவத்தில், இது சிறிய பயன்பாடாகும்:

public boolean equals(Object obj) {
   return (this == obj);
}
இந்த முறை வகுப்பில் எவ்வாறு equals()வரையறுக்கப்படுகிறது Object. இது மீண்டும் ஒருமுறை குறிப்புகளின் ஒப்பீடு. ஏன் அப்படி செய்தார்கள்? சரி, உங்கள் நிரலில் எந்தெந்தப் பொருள்கள் சமமாகக் கருதப்படுகின்றன, எவை இல்லை என்று மொழியின் படைப்பாளிகளுக்கு எப்படித் தெரியும்? :) இது முறையின் முக்கிய அம்சமாகும் equals()— வகுப்பின் பொருள்களின் சமத்துவத்தை சரிபார்க்கும் போது எந்தெந்த பண்புகள் பயன்படுத்தப்படுகின்றன என்பதை தீர்மானிப்பவர் ஒரு வகுப்பை உருவாக்கியவர். equals()உங்கள் வகுப்பில் உள்ள முறையை நீங்கள் மேலெழுதுகிறீர்கள் . "எந்த குணாதிசயங்களை தீர்மானிக்கிறது" என்பதன் அர்த்தத்தை நீங்கள் புரிந்து கொள்ளவில்லை என்றால், ஒரு உதாரணத்தை கருத்தில் கொள்வோம். ஒரு மனிதனைக் குறிக்கும் எளிய வகுப்பு இங்கே: Man.

public class Man {

   private String noseSize;
   private String eyesColor;
   private String haircut;
   private boolean scars;
   private int dnaCode;

public Man(String noseSize, String eyesColor, String haircut, boolean scars, int dnaCode) {
   this.noseSize = noseSize;
   this.eyesColor = eyesColor;
   this.haircut = haircut;
   this.scars = scars;
   this.dnaCode = dnaCode;
}

   // Getters, setters, etc.
}
இரண்டு பேர் ஒரே மாதிரியான இரட்டையர்களா அல்லது வெறுமனே தோற்றமளிக்கிறார்களா என்பதை தீர்மானிக்க வேண்டிய ஒரு நிரலை நாங்கள் எழுதுகிறோம் என்று வைத்துக்கொள்வோம். எங்களிடம் ஐந்து குணாதிசயங்கள் உள்ளன: மூக்கின் அளவு, கண் நிறம், முடி நடை, வடுக்கள் இருப்பது மற்றும் டிஎன்ஏ சோதனை முடிவுகள் (எளிமைக்காக, இதை முழு எண் குறியீடாகக் குறிப்பிடுகிறோம்). இந்த குணாதிசயங்களில் எது ஒரே மாதிரியான இரட்டையர்களை அடையாளம் காண எங்கள் நிரலை அனுமதிக்கும் என்று நீங்கள் நினைக்கிறீர்கள்? சம மற்றும் ஹாஷ்கோட் முறைகள்: சிறந்த நடைமுறைகள் - 2நிச்சயமாக, டிஎன்ஏ சோதனை மட்டுமே உத்தரவாதத்தை அளிக்க முடியும். இரண்டு நபர்களுக்கு ஒரே மாதிரியான கண் நிறம், ஹேர்கட், மூக்கு மற்றும் தழும்புகள் கூட இருக்கலாம் - உலகில் நிறைய பேர் உள்ளனர், மேலும் அங்கு டாப்பல்கெங்கர்கள் இல்லை என்று உத்தரவாதம் அளிக்க முடியாது. ஆனால் எங்களுக்கு நம்பகமான வழிமுறை தேவை: டிஎன்ஏ சோதனையின் முடிவு மட்டுமே துல்லியமான முடிவை எடுக்க அனுமதிக்கும். இது எங்கள் முறைக்கு என்ன அர்த்தம் equals()? நாம் அதை மேலெழுத வேண்டும்Manவகுப்பு, எங்கள் திட்டத்தின் தேவைகளை கணக்கில் எடுத்துக்கொள்கிறது. முறை int dnaCodeஇரண்டு பொருள்களின் புலத்தை ஒப்பிட வேண்டும். அவை சமமாக இருந்தால், பொருள்களும் சமம்.

@Override
public boolean equals(Object o) {
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
இது உண்மையில் அவ்வளவு எளிமையானதா? உண்மையில் இல்லை. நாங்கள் எதையாவது கவனிக்கவில்லை. எங்கள் பொருள்களுக்கு, பொருள் சமத்துவத்தை நிறுவுவதற்கு பொருத்தமான ஒரு புலத்தை மட்டுமே நாங்கள் அடையாளம் கண்டுள்ளோம்: dnaCode. இப்போது எங்களிடம் 1 இல்லை, ஆனால் 50 தொடர்புடைய புலங்கள் இருப்பதாக கற்பனை செய்து பாருங்கள். இரண்டு பொருள்களின் 50 புலங்களும் சமமாக இருந்தால், பொருள்கள் சமம். அத்தகைய காட்சியும் சாத்தியமாகும். முக்கிய பிரச்சனை என்னவென்றால், 50 துறைகளை ஒப்பிடுவதன் மூலம் சமத்துவத்தை நிலைநிறுத்துவது நேரத்தைச் செலவழிக்கும் மற்றும் வளங்களைக் கொண்ட செயல்முறையாகும். இப்போது கற்பனை செய்து பாருங்கள், எங்கள் வகுப்பிற்கு கூடுதலாக Man, எங்களிடம் Womanஉள்ள அதே புலங்களைக் கொண்ட ஒரு வகுப்பு உள்ளது Man. வேறொரு புரோகிராமர் எங்கள் வகுப்புகளைப் பயன்படுத்தினால், அவர் அல்லது அவள் இது போன்ற குறியீட்டை எளிதாக எழுதலாம்:

public static void main(String[] args) {
  
   Man man = new Man(........); // A bunch of parameters in the constructor

   Woman woman = new Woman(.........); // The same bunch of parameters.

   System.out.println(man.equals(woman));
}
இந்த விஷயத்தில், புல மதிப்புகளைச் சரிபார்ப்பது அர்த்தமற்றது: நம்மிடம் இரண்டு வெவ்வேறு வகுப்புகளின் பொருள்கள் இருப்பதை உடனடியாகக் காணலாம், எனவே அவை சமமாக இருக்க வழி இல்லை! அதாவது, equals()ஒப்பிடப்பட்ட பொருட்களின் வகுப்புகளை ஒப்பிட்டு, முறைக்கு ஒரு காசோலையைச் சேர்க்க வேண்டும். என்று நாம் சிந்திப்பது நல்லது!

@Override
public boolean equals(Object o) {
   if (getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
ஆனால் ஒருவேளை நாம் வேறு ஏதாவது மறந்துவிட்டோமா? ஹ்ம்ம்... குறைந்தபட்சம், நாம் ஒரு பொருளை தன்னுடன் ஒப்பிடவில்லையா என்பதை சரிபார்க்க வேண்டும்! குறிப்புகள் A மற்றும் B ஒரே நினைவக முகவரியைச் சுட்டிக்காட்டினால், அவை ஒரே பொருளாகும், மேலும் நேரத்தை வீணடித்து 50 புலங்களை ஒப்பிட வேண்டிய அவசியமில்லை.

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
காசோலையைச் சேர்ப்பதும் வலிக்காது null: எந்த பொருளும் சமமாக இருக்க முடியாது null. எனவே, முறை அளவுரு பூஜ்யமாக இருந்தால், கூடுதல் சரிபார்ப்புகளில் எந்த அர்த்தமும் இல்லை. இவை அனைத்தையும் கருத்தில் கொண்டு, வகுப்பிற்கான எங்கள் equals()முறை Manஇதுபோல் தெரிகிறது:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;
   Man man = (Man) o;
   return dnaCode == man.dnaCode;
}
மேலே குறிப்பிட்டுள்ள அனைத்து ஆரம்ப சோதனைகளையும் நாங்கள் செய்கிறோம். நாள் முடிவில், என்றால்:
  • நாங்கள் ஒரே வகுப்பின் இரண்டு பொருட்களை ஒப்பிடுகிறோம்
  • மற்றும் ஒப்பிடப்பட்ட பொருள்கள் ஒரே பொருள் அல்ல
  • மற்றும் அனுப்பப்பட்ட பொருள் இல்லைnull
...பின்னர் தொடர்புடைய குணாதிசயங்களை ஒப்பிட்டுப் பார்க்கிறோம். எங்களைப் பொறுத்தவரை, இது dnaCodeஇரண்டு பொருட்களின் புலங்கள் என்று பொருள். முறையை மீறும் போது equals(), ​​பின்வரும் தேவைகளை கவனிக்க வேண்டும்:
  1. பிரதிபலிப்பு.

    equals()எந்தவொரு பொருளையும் தன்னுடன் ஒப்பிட்டுப் பார்க்கும் முறை பயன்படுத்தப்படும்போது, ​​அது உண்மையாகத் திரும்ப வேண்டும் .
    இந்த தேவைக்கு நாங்கள் ஏற்கனவே இணங்கிவிட்டோம். எங்கள் முறை அடங்கும்:

    
    if (this == o) return true;
    

  2. சமச்சீர்.

    என்றால் a.equals(b) == true, b.equals(a)திரும்ப வேண்டும் true.
    எங்கள் முறை இந்த தேவையையும் பூர்த்தி செய்கிறது.

  3. டிரான்சிட்டிவிட்டி.

    இரண்டு பொருள்கள் சில மூன்றாவது பொருளுக்கு சமமாக இருந்தால், அவை ஒன்றுக்கொன்று சமமாக இருக்க வேண்டும்.
    என்றால் a.equals(b) == trueமற்றும் a.equals(c) == true, பின்னர் b.equals(c)உண்மையும் திரும்ப வேண்டும்.

  4. விடாமுயற்சி.

    equals()சம்பந்தப்பட்ட துறைகள் மாற்றப்படும் போது மட்டுமே முடிவு மாற வேண்டும். இரண்டு பொருள்களின் தரவு மாறவில்லை என்றால், அதன் முடிவு equals()எப்போதும் ஒரே மாதிரியாக இருக்க வேண்டும்.

  5. உடன் சமத்துவமின்மை null.

    எந்தவொரு பொருளுக்கும், a.equals(null)தவறை வழங்க வேண்டும்
    இது சில "பயனுள்ள பரிந்துரைகளின்" தொகுப்பு மட்டும் அல்ல, மாறாக ஆரக்கிள் ஆவணத்தில் குறிப்பிடப்பட்டுள்ள கடுமையான ஒப்பந்தம்

hashCode() முறை

இப்போது முறை பற்றி பேசலாம் hashCode(). அது ஏன் அவசியம்? அதே நோக்கத்திற்காக - பொருட்களை ஒப்பிடுவதற்கு. ஆனால் எங்களிடம் ஏற்கனவே உள்ளது equals()! ஏன் மற்றொரு முறை? பதில் எளிது: செயல்திறனை மேம்படுத்த. முறையைப் பயன்படுத்தி ஜாவாவில் குறிப்பிடப்படும் ஹாஷ் செயல்பாடு hashCode(), எந்தவொரு பொருளுக்கும் நிலையான நீள எண் மதிப்பை வழங்குகிறது. ஜாவாவில், இந்த முறை எந்த பொருளுக்கும் hashCode()32-பிட் எண்ணை ( ) வழங்கும் . intஇந்த முறையைப் பயன்படுத்தி இரண்டு பொருள்களை ஒப்பிடுவதை விட இரண்டு எண்களை ஒப்பிடுவது மிக வேகமாக இருக்கும் equals(), குறிப்பாக அந்த முறை பல புலங்களைக் கருத்தில் கொண்டால். எங்கள் நிரல் பொருட்களை ஒப்பிட்டுப் பார்த்தால், ஹாஷ் குறியீட்டைப் பயன்படுத்தி இதைச் செய்வது மிகவும் எளிதானது. முறையின் அடிப்படையில் பொருள்கள் சமமாக இருந்தால் மட்டுமே hashCode()ஒப்பீடு தொடரும்equals()முறை. மூலம், ஹாஷ் அடிப்படையிலான தரவு கட்டமைப்புகள் இப்படித்தான் செயல்படுகின்றன, எடுத்துக்காட்டாக, பழக்கமானவை HashMap! முறையைப் hashCode()போலவே, இந்த equals()முறையும் டெவலப்பரால் மேலெழுதப்படுகிறது. மேலும் equals(), hashCode()முறையானது ஆரக்கிள் ஆவணத்தில் உத்தியோகபூர்வ தேவைகளைக் கொண்டுள்ளது:
  1. இரண்டு பொருள்கள் சமமாக இருந்தால் (அதாவது equals()முறை உண்மையாக இருக்கும்), பின்னர் அவை ஒரே ஹாஷ் குறியீட்டைக் கொண்டிருக்க வேண்டும்.

    இல்லையெனில், எங்கள் முறைகள் அர்த்தமற்றதாகிவிடும். நாம் மேலே குறிப்பிட்டுள்ளபடி, hashCode()செயல்திறனை மேம்படுத்த முதலில் ஒரு காசோலை செல்ல வேண்டும். ஹாஷ் குறியீடுகள் வேறுபட்டிருந்தால், காசோலை தவறானதாகத் திரும்பும், பொருள்கள் உண்மையில் சமமாக இருந்தாலும், நாங்கள் முறையை வரையறுத்துள்ளோம் equals().

  2. hashCode()ஒரே பொருளில் முறை பல முறை அழைக்கப்பட்டால், அது ஒவ்வொரு முறையும் அதே எண்ணை வழங்க வேண்டும் .

  3. விதி 1 எதிர் திசையில் வேலை செய்யாது. இரண்டு வெவ்வேறு பொருள்கள் ஒரே ஹாஷ் குறியீட்டைக் கொண்டிருக்கலாம்.

மூன்றாவது விதி சற்று குழப்பமானது. இது எப்படி முடியும்? விளக்கம் மிகவும் எளிமையானது. முறை hashCode()ஒரு int. An intஎன்பது 32-பிட் எண். இது வரையறுக்கப்பட்ட மதிப்புகளைக் கொண்டுள்ளது: -2,147,483,648 முதல் +2,147,483,647 வரை. வேறு வார்த்தைகளில் கூறுவதானால், ஒரு 4 பில்லியனுக்கும் அதிகமான சாத்தியமான மதிப்புகள் உள்ளன int. இப்போது நீங்கள் பூமியில் வாழும் அனைத்து மக்களைப் பற்றிய தரவையும் சேமிக்க ஒரு நிரலை உருவாக்குகிறீர்கள் என்று கற்பனை செய்து பாருங்கள். ஒவ்வொரு நபரும் அதன் சொந்த பொருளை ஒத்திருப்பார்கள் Person(வகுப்பைப் போன்றது Man). பூமியில் ~7.5 பில்லியன் மக்கள் வாழ்கின்றனர். வேறு வார்த்தைகளில் கூறுவதானால், மாற்றுவதற்கு நாம் எழுதும் அல்காரிதம் எவ்வளவு புத்திசாலித்தனமாக இருந்தாலும் சரிPersonஒரு எண்ணுக்கு பொருள்கள், எங்களிடம் போதுமான சாத்தியமான எண்கள் இல்லை. எங்களிடம் 4.5 பில்லியன் சாத்தியமான முழு மதிப்புகள் மட்டுமே உள்ளன, ஆனால் அதை விட அதிகமான மக்கள் உள்ளனர். அதாவது, நாம் எவ்வளவு கடினமாக முயற்சித்தாலும், சில வேறுபட்ட நபர்களுக்கு ஒரே ஹாஷ் குறியீடுகள் இருக்கும். இது நிகழும்போது (ஹாஷ் குறியீடுகள் இரண்டு வெவ்வேறு பொருள்களுக்கு இணைகின்றன) அதை மோதல் என்று அழைக்கிறோம். முறையை மேலெழுதும்போது hashCode(), ​​புரோகிராமரின் நோக்கங்களில் ஒன்று மோதல்களின் சாத்தியமான எண்ணிக்கையைக் குறைப்பதாகும். இந்த விதிகள் அனைத்தையும் கணக்கிட்டால், hashCode()வகுப்பில் முறை எப்படி இருக்கும் Person? இது போன்ற:

@Override
public int hashCode() {
   return dnaCode;
}
ஆச்சரியமா? :) நீங்கள் தேவைகளைப் பார்த்தால், அவை அனைத்தையும் நாங்கள் கடைப்பிடிக்கிறோம் என்பதை நீங்கள் காண்பீர்கள். எங்கள் equals()முறை உண்மையாகத் திரும்பும் பொருள்களும் க்கு ஏற்ப சமமாக இருக்கும் hashCode(). நமது இரண்டு Personபொருள்களும் சமமாக இருந்தால் equals(அதாவது, அவை ஒரே மாதிரியானவை dnaCode), எங்கள் முறை அதே எண்ணை வழங்குகிறது. மிகவும் கடினமான உதாரணத்தைக் கருத்தில் கொள்வோம். எங்கள் திட்டம் கார் சேகரிப்பாளர்களுக்கு சொகுசு கார்களைத் தேர்ந்தெடுக்க வேண்டும் என்று வைத்துக்கொள்வோம். சேகரிப்பது பல தனித்தன்மைகளைக் கொண்ட ஒரு சிக்கலான பொழுதுபோக்காக இருக்கலாம். ஒரு குறிப்பிட்ட 1963 கார் 1964 காரை விட 100 மடங்கு அதிகமாகும். 1970 ஆம் ஆண்டு சிவப்பு கார் அதே ஆண்டு அதே பிராண்டின் நீல நிற காரை விட 100 மடங்கு அதிகமாக செலவாகும். சம மற்றும் ஹாஷ்கோட் முறைகள்: சிறந்த நடைமுறைகள் - 4எங்கள் முந்தைய எடுத்துக்காட்டில், வகுப்பில் Person, பெரும்பாலான துறைகளை (அதாவது மனித குணாதிசயங்கள்) முக்கியமற்றவை என்று நிராகரித்தோம், மேலும்dnaCodeஒப்பீடுகளில் களம். நாங்கள் இப்போது மிகவும் தனித்தன்மை வாய்ந்த உலகில் வேலை செய்கிறோம், அதில் முக்கியமற்ற விவரங்கள் எதுவும் இல்லை! இங்கே எங்கள் LuxuryAutoவகுப்பு:

public class LuxuryAuto {

   private String model;
   private int manufactureYear;
   private int dollarPrice;

   public LuxuryAuto(String model, int manufactureYear, int dollarPrice) {
       this.model = model;
       this.manufactureYear = manufactureYear;
       this.dollarPrice = dollarPrice;
   }

   // ...getters, setters, etc.
}
இப்போது நாம் நமது ஒப்பீடுகளில் அனைத்து துறைகளையும் கருத்தில் கொள்ள வேண்டும். எந்தவொரு தவறும் ஒரு வாடிக்கையாளருக்கு நூறாயிரக்கணக்கான டாலர்கள் செலவாகும், எனவே அதிகப்படியான பாதுகாப்பாக இருப்பது நல்லது:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;

   LuxuryAuto that = (LuxuryAuto) o;

   if (manufactureYear != that.manufactureYear) return false;
   if (dollarPrice != that.dollarPrice) return false;
   return model.equals(that.model);
}
எங்கள் equals()முறையில், நாங்கள் முன்பு பேசிய அனைத்து காசோலைகளையும் நாங்கள் மறந்துவிடவில்லை. ஆனால் இப்போது நாம் நமது பொருள்களின் மூன்று துறைகளில் ஒவ்வொன்றையும் ஒப்பிட்டுப் பார்க்கிறோம். இந்த திட்டத்திற்கு, எங்களுக்கு முழுமையான சமத்துவம் தேவை, அதாவது ஒவ்வொரு துறையின் சமத்துவம். பற்றி என்ன hashCode?

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = result + manufactureYear;
   result = result + dollarPrice;
   return result;
}
எங்கள் வகுப்பில் உள்ள புலம் modelஒரு சரம். இது வசதியானது, ஏனெனில் Stringவகுப்பு ஏற்கனவே முறையை மீறுகிறது hashCode(). புலத்தின் ஹாஷ் குறியீட்டைக் கணக்கிட்டு model, மற்ற இரண்டு எண் புலங்களின் கூட்டுத்தொகையை அதில் சேர்க்கிறோம். ஜாவா டெவலப்பர்கள் மோதல்களின் எண்ணிக்கையைக் குறைக்கப் பயன்படுத்தும் எளிய தந்திரத்தைக் கொண்டுள்ளனர்: ஹாஷ் குறியீட்டைக் கணக்கிடும் போது, ​​இடைநிலை முடிவை ஒற்றைப்படைப் பிரைம் மூலம் பெருக்கவும். பொதுவாகப் பயன்படுத்தப்படும் எண் 29 அல்லது 31. நாம் இப்போது கணித நுணுக்கங்களை ஆராய மாட்டோம், ஆனால் எதிர்காலத்தில் இடைநிலை முடிவுகளை போதுமான பெரிய ஒற்றைப்படை எண்ணால் பெருக்குவது ஹாஷ் செயல்பாட்டின் முடிவுகளை "பரவுவதற்கு" உதவுகிறது என்பதை நினைவில் கொள்ளுங்கள். இதன் விளைவாக, ஒரே ஹாஷ் குறியீட்டைக் கொண்ட பொருள்களின் எண்ணிக்கையைக் குறைக்கவும். LuxuryAuto இல் எங்கள் hashCode()முறைக்கு, இது இப்படி இருக்கும்:

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = 31 * result + manufactureYear;
   result = 31 * result + dollarPrice;
   return result;
}
இந்த பொறிமுறையின் அனைத்து நுணுக்கங்களையும் பற்றி ஸ்டாக்ஓவர்ஃப்ளோவில் உள்ள இந்த இடுகையிலும் , ஜோசுவா ப்ளாச்சின் எஃபெக்டிவ் ஜாவா புத்தகத்திலும் நீங்கள் மேலும் படிக்கலாம். இறுதியாக, குறிப்பிடத் தகுந்த மற்றொரு முக்கியமான விஷயம். ஒவ்வொரு முறையும் நாங்கள் equals()மற்றும் hashCode()முறையை மீறுகிறோம், இந்த முறைகளில் கணக்கில் எடுத்துக்கொள்ளப்படும் சில நிகழ்வு புலங்களைத் தேர்ந்தெடுத்தோம். இந்த முறைகள் அதே துறைகளை கருதுகின்றன. equals()ஆனால் பல்வேறு துறைகளை நாம் கருத்தில் கொள்ளலாமா hashCode()? தொழில்நுட்ப ரீதியாக, நம்மால் முடியும். ஆனால் இது ஒரு மோசமான யோசனை, அதற்கான காரணம் இங்கே:

@Override
public boolean equals(Object o) {
   if (this == o) return true;
   if (o == null || getClass() != o.getClass()) return false;

   LuxuryAuto that = (LuxuryAuto) o;

   if (manufactureYear != that.manufactureYear) return false;
   return dollarPrice == that.dollarPrice;
}

@Override
public int hashCode() {
   int result = model == null ? 0 : model.hashCode();
   result = 31 * result + manufactureYear;
   result = 31 * result + dollarPrice;
   return result;
}
வகுப்பிற்கான எங்கள் equals()மற்றும் முறைகள் இங்கே . முறை மாறாமல் இருந்தது, ஆனால் முறையிலிருந்து புலத்தை அகற்றினோம் . முறை இரண்டு பொருட்களை ஒப்பிடும் போது மாதிரியானது இனி ஒரு பண்பு அல்ல . ஆனால் ஹாஷ் குறியீட்டை கணக்கிடும் போது, ​​அந்த புலம் இன்னும் கணக்கில் எடுத்துக்கொள்ளப்படுகிறது. இதன் விளைவாக நாம் என்ன பெறுகிறோம்? இரண்டு கார்களை உருவாக்கி கண்டுபிடிப்போம்! hashCode()LuxuryAutohashCode()modelequals()equals()

public class Main {

   public static void main(String[] args) {

       LuxuryAuto ferrariGTO = new LuxuryAuto("Ferrari 250 GTO", 1963, 70000000);
       LuxuryAuto ferrariSpider = new LuxuryAuto("Ferrari 335 S Spider Scaglietti", 1963, 70000000);

       System.out.println("Are these two objects equal to each other?");
       System.out.println(ferrariGTO.equals(ferrariSpider));

       System.out.println("What are their hash codes?");
       System.out.println(ferrariGTO.hashCode());
       System.out.println(ferrariSpider.hashCode());
   }
}

Are these two objects equal to each other? 
true 
What are their hash codes? 
-1372326051 
1668702472
பிழை! பல்வேறு துறைகள் equals()மற்றும் hashCode()முறைகளைப் பயன்படுத்துவதன் மூலம், அவர்களுக்காக ஏற்படுத்தப்பட்ட ஒப்பந்தங்களை நாங்கள் மீறினோம்! முறையின்படி சமமாக இருக்கும் இரண்டு பொருள்கள் equals()ஒரே ஹாஷ் குறியீட்டைக் கொண்டிருக்க வேண்டும். அவர்களுக்காக வெவ்வேறு மதிப்புகளைப் பெற்றோம். இத்தகைய பிழைகள் முற்றிலும் நம்பமுடியாத விளைவுகளுக்கு வழிவகுக்கும், குறிப்பாக ஹாஷைப் பயன்படுத்தும் சேகரிப்புகளுடன் பணிபுரியும் போது. இதன் விளைவாக, நீங்கள் மேலெழுதும்போது equals()மற்றும் hashCode(), அதே புலங்களை நீங்கள் கருத்தில் கொள்ள வேண்டும். இந்த பாடம் நீண்டது, ஆனால் இன்று நீங்கள் நிறைய கற்றுக்கொண்டீர்கள்! :) இப்போது பணிகளைத் தீர்க்கத் திரும்புவதற்கான நேரம் இது!
கருத்துக்கள்
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION