equals
алоқаманданд hashCode
ва тавсия дода мешавад, ки ҳардуи ин усулҳоро дар синфҳои худ пайваста барҳам диҳед. Шумораи каме камтар медонад, ки чаро ин тавр аст ва агар ин қоида вайрон карда шавад, чӣ оқибатҳои ғамангез ба амал меоянд. Ман пешниҳод мекунам, ки мафҳуми ин усулҳоро баррасӣ карда, ҳадафи онҳоро такрор кунед ва фаҳмед, ки чаро онҳо ин қадар пайвастанд. Ман ин мақоларо ба мисли мақолаи қаблӣ дар бораи боркунии синфҳо барои худ навиштам, то дар ниҳоят тамоми ҷузъиёти масъаларо ошкор кунам ва дигар ба манбаъҳои тарафи сеюм барнагардам. Бинобар ин ман аз танкиди конструктивй шод хохам шуд, зеро агар дар ягон чо камбудихо мавчуд бошанд, бояд бартараф карда шаванд. Мақола, мутаассифона, хеле дароз шуд.
ба қоидаҳои бекоркунӣ баробар аст
Усулиequals()
дар Java барои тасдиқ ё рад кардани далели мантиқӣ баробар будани ду an objectи пайдоиши якхела лозим аст . Яъне, ҳангоми муқоисаи ду an object, барномасоз бояд фаҳмад, ки майдонҳои муҳими онҳо баробаранд . Зарур нест, ки ҳамаи майдонҳо бояд якхела бошанд, зеро усул баробарии мантиқироequals()
дар назар дорад . Аммо баъзан барои истифодаи ин усул зарурати махсус вуҷуд надорад. Тавре ки мегӯянд, роҳи осонтарини пешгирӣ кардани мушкилот бо истифодаи механизми мушаххас ин истифода набурдани он аст. Инчунин бояд қайд кард, ки вақте ки шумо шартномаро вайрон мекунед, шумо назоратро дарк мекунед, ки чӣ гуна an objectҳо ва сохторҳои дигар бо an objectи шумо ҳамкорӣ мекунанд. Ва баъдан пайдо кардани сабаби хатогӣ хеле душвор хоҳад буд. equals
Вақте ки ин усулро аз байн набаред
- Вақте ки ҳар як мисоли синф беназир аст. Ба андозаи бештар, ин ба он синфҳое дахл дорад, ки рафтори мушаххасро таъмин мекунанд, на барои кор бо маълумот. Масалан, ба монанди синф
- Ҳангоме ки дар асл аз синф талаб карда намешавад, ки эквивалентии мисолҳои онро муайян кунад. Масалан, барои синф
- Вақте ки синфе, ки шумо васеъ мекунед, аллакай татбиқи усули худро дорад
equals
ва рафтори ин татбиқ ба шумо мувофиқ аст. Масалан, барои синфҳои - Ва дар ниҳоят, ҳеҷ зарурате нест,
equals
ки кай доираи синфи шумостprivate
ё астpackage-private
ва шумо боварӣ доред, ки ин усул ҳеҷ гоҳ даъват карда намешавад.
Thread
. Барои онҳо equals
, татбиқи усули пешниҳодкардаи синф Object
беш аз кофист. Мисоли дигар синфҳои enum ( Enum
).
java.util.Random
барои муқоисаи мисолҳои синф бо ҳамдигар, муайян кардани он, ки оё онҳо метавонанд як пайдарпаии рақамҳои тасодуфиро баргардонанд, умуман лозим нест. Танҳо аз сабаби он ки табиати ин синф ҳатто чунин рафторро дар назар надорад.
Set
, List
, Map
татбиқ equals
дар AbstractSet
, AbstractList
ва AbstractMap
мувофиқ аст.
шартнома баробар аст
Ҳангоми бекор кардани усул,equals
таҳиякунанда бояд қоидаҳои асосии дар мушаххасоти забони Java муайяншударо риоя кунад.
- Рефлексия барои ҳар як арзиши додашуда
- Симметрия барои ҳама арзишҳои додашуда
- Гузариш барои ҳар як арзишҳои додашуда ва
- Мутобиқати барои ҳар як арзишҳои додашуда
- Муқоиса null барои ҳар як арзиши додашуда
x
, ифода x.equals(x)
бояд баргардад true
.
Дода - чунин маъно дорад
x != null
x
ва y
, x.equals(y)
бояд true
танҳо дар сурати y.equals(x)
баргардонидани он баргардад true
.
x
агар y
баргардад z
ва баргардад , бояд арзишро баргардонад . x.equals(y)
true
y.equals(z)
true
x.equals(z)
true
x
ва y
занги такрорӣ x.equals(y)
арзиши занги қаблиро ба ин усул бармегардонад, ба шарте ки майдонҳои барои муқоисаи ду an object истифодашуда дар байни зангҳо тағир наёбанд.
x
занг x.equals(null)
бояд баргардад false
.
ба вайрон кардани шартнома баробар аст
Бисёр синфҳо, ба монанди синфҳои Java Collections Framework, аз татбиқи метод вобастаандequals()
, бинобар ин шумо набояд онро сарфи назар кунед, зеро Вайрон кардани шартномаи ин усул метавонад боиси беақлона кор кардани ариза гардад ва дар ин ҳолат пайдо кардани сабаб хеле душвор хоҳад буд. Тибқи принсипи рефлексивӣ , ҳар як an object бояд ба худ баробар бошад. Агар ин принсип вайрон карда шавад, вақте ки мо an objectро ба коллексия илова мекунем ва сипас онро бо истифода аз усул ҷустуҷӯ мекунем, contains()
мо an objectеро, ки нав ба коллексия илова кардем, ёфта наметавонем. Шарти симметрия изҳор мекунад, ки ҳар ду an object новобаста аз тартиби муқоисаи онҳо бояд баробар бошанд. equals
Масалан, агар шумо синфе дошта бошед, ки танҳо як майдони навъи сатр дошта бошад, муқоисаи ин майдон бо сатри усул нодуруст хоҳад буд . Зеро дар сурати муқоисаи баръакс, усул ҳамеша арзиши false
.
// Нарушение симметричности
public class SomeStringify {
private String s;
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o instanceof SomeStringify) {
return s.equals(((SomeStringify) o).s);
}
// нарушение симметричности, классы разного происхождения
if (o instanceof String) {
return s.equals(o);
}
return false;
}
}
//Правильное определение метода equals
@Override
public boolean equals(Object o) {
if (this == o) return true;
return o instanceof SomeStringify &&
((SomeStringify) o).s.equals(s);
}
Аз шарти гузариш чунин бармеояд, ки агар яке аз се an object баробар бошад, дар ин маврид хар се бояд баробар бошанд. Ин принсипро ба осонӣ вайрон кардан мумкин аст, вақте ки зарурати васеъ кардани синфи муайяни базавӣ тавассути илова кардани ҷузъи муҳим ба он . Масалан, ба синф Point
бо координатҳо x
ва y
шумо бояд ранги нуқтаро бо васеъ кардани он илова кунед. Барои ин ба шумо лозим меояд, ки синферо ColorPoint
бо майдони мувофиқ эълон кунед color
. Ҳамин тариқ, агар дар синфи васеъшуда мо equals
усули волидайнро меномем ва дар волидайн мо тахмин кунем, ки танҳо координатҳо x
ва муқоиса карда мешаванд y
, пас ду нуқтаи рангҳои гуногун, вале координатаҳои якхела баробар ҳисобида мешаванд, ки ин нодуруст аст. Дар ин ҳолат ба синфи ҳосилшуда барои фарқ кардани рангҳо ёд додан лозим аст. Барои ин, шумо метавонед ду усулро истифода баред. Аммо яке қоидаи симметрияро вайрон мекунад ва дуюм - транзитивӣ .
// Первый способ, нарушая симметричность
// Метод переопределен в классе ColorPoint
@Override
public boolean equals(Object o) {
if (!(o instanceof ColorPoint)) return false;
return super.equals(o) && ((ColorPoint) o).color == color;
}
Дар ин ҳолат, занг point.equals(colorPoint)
арзиши true
, ва муқоиса colorPoint.equals(point)
бармегардад false
, зеро an objectи синфи «он»-ро интизор аст. Хамин тавр, коидаи симметрия вайрон карда мешавад. Усули дуюм гузаронидани санҷиши "кӯр" -ро дар бар мегирад, агар дар бораи ранги нуқта маълумот мавҷуд набошад, яъне мо синф дорем Point
. Ё рангро тафтиш кунед, агар маълумот дар бораи он мавҷуд бошад, яъне an objectи синфро муқоиса кунед ColorPoint
.
// Метод переопределен в классе ColorPoint
@Override
public boolean equals(Object o) {
if (!(o instanceof Point)) return false;
// Слепая проверка
if (!(o instanceof ColorPoint))
return super.equals(o);
// Полная проверка, включая цвет точки
return super.equals(o) && ((ColorPoint) o).color == color;
}
Дар ин чо принципи гузариш ба таври зерин вайрон карда мешавад. Фарз мекунем, ки таърифи an objectҳои зерин вуҷуд дорад:
ColorPoint p1 = new ColorPoint(1, 2, Color.RED);
Point p2 = new Point(1, 2);
ColorPoint p3 = new ColorPoint(1, 2, Color.BLUE);
Ҳамин тариқ, гарчанде ки баробарӣ p1.equals(p2)
ва қаноатманд аст p2.equals(p3)
, p1.equals(p3)
он арзишро бармегардонад false
. Дар баробари ин, усули дуюм, ба назари ман, камтар ҷолиб менамояд, зеро Дар баъзе мавридҳо, алгоритм метавонад нобино бошад ва муқоисаро пурра иҷро накунад ва шумо дар ин бора хабар надоред. Каме шеър Умуман, чунон ки ман мефахмам, халли конкретии ин масъала нест. Як андешаи як муаллифи бонуфуз бо номи Кей Хорстман вуҷуд дорад, ки шумо метавонед истифодаи операторро instanceof
бо занги методе иваз кунед getClass()
, ки синфи an objectро бармегардонад ва пеш аз оғози муқоисаи худи an objectҳо, боварӣ ҳосил кунед, ки онҳо як навъанд. , ва ба факти умумии пайдоиши онхо эътибор намедиханд. Ҳамин тариқ, қоидаҳои симметрия ва транзитивӣ қонеъ карда мешаванд. Аммо дар айни замон, дар тарафи дигари баррикада як муаллифи дигар, ки дар доираҳои васеъ эҳтиром надорад, Ҷошуа Блох меистад, ки бар ин назар аст, ки ин бархӯрд принсипи ивазкунии Барбара Лисковро вайрон мекунад. Ин принсип мегӯяд, ки "codeи занг бояд ба синфи асосӣ ҳамон тавре ки зерсинфҳои он бидуни донистани он муносибат кунад . " Ва дар халли пешниходкардаи Хорстман ин принцип ба таври равшан вайрон карда мешавад, зеро ин ба татбики он вобаста аст. Хулоса, маълум аст, ки масъала торик аст. Инчунин бояд қайд кард, ки Хорстманн қоидаи татбиқи равиши худро равшан мекунад ва бо забони оддии англисӣ менависад, ки шумо бояд ҳангоми таҳияи дарсҳо дар бораи стратегия қарор қабул кунед ва агар санҷиши баробарӣ танҳо аз ҷониби суперкласс гузаронида шавад, шумо метавонед ин корро тавассути иҷрои амалиёт instanceof
. Дар акси ҳол, вақте ки семантикаи чек вобаста ба синфи ҳосилшуда тағир меёбад ва татбиқи усул бояд ба зинанизоми поён кӯчонида шавад, шумо бояд усули getClass()
. Ҷошуа Блоч, дар навбати худ, пешниҳод мекунад, ки меросро тарк кунанд ва таркиби an objectро тавассути дохил кардани ColorPoint
синф ба синф Point
ва пешниҳоди усули дастрасӣ asPoint()
барои ба даст овардани маълумот дар бораи нуқта истифода баранд. Ин аз вайрон кардани ҳама қоидаҳо пешгирӣ мекунад, аммо, ба андешаи ман, фаҳмидани codeро душвортар мекунад. Варианти сеюм ин истифодаи тавлиди автоматии усули баробар бо истифода аз IDE мебошад. Дар омади гап, идея насли Horstmann-ро таҷдид мекунад, ки ба шумо имкон медиҳад стратегияи татбиқи усулро дар суперкласс ё наслҳои он интихоб кунед. Ниҳоят, қоидаи мувофиқати навбатӣ мегӯяд, ки ҳатто агар an objectҳо тағир x
наёбанд y
, дубора даъват кардани онҳо x.equals(y)
бояд ҳамон арзиши қаблиро баргардонад. Қоидаи ниҳоӣ ин аст, ки ҳеҷ як an object набояд ба null
. Дар ин ҷо ҳама чиз равшан аст null
- ин номуайянӣ аст, оё an object ба номуайянӣ баробар аст? Маълум нест, яъне false
.
Алгоритми умумӣ барои муайян кардани баробарҳо
- Санҷед, ки баробарии истинодҳои an objectҳо
this
ва параметрҳои методo
.if (this == o) return true;
- Санҷед, ки оё пайванд муайян шудааст
o
, яъне оё он астnull
.
Агар дар оянда ҳангоми муқоисаи намудҳои an objectҳо оператор истифода шавадinstanceof
, ин ҷузъро партофтан мумкин аст, зеро ин параметрfalse
дар ин ҳолат бармегардадnull instanceof Object
. - Навъҳои an objectро
this
бо истифода азo
операторinstanceof
ё усулgetClass()
, ки аз рӯи тавсифи дар боло овардашуда ва интуитсияи шахсии худ роҳнамоӣ мекунанд, муқоиса кунед. - Агар усул
equals
дар зерсинф бекор карда шуда бошад, ҳатман занг занедsuper.equals(o)
- Навъи параметрро
o
ба синфи зарурӣ табдил диҳед. - Муқоисаи ҳамаи майдонҳои an objectи муҳимро иҷро кунед:
- барои намудҳои ибтидоӣ (ба истиснои
float
ваdouble
), бо истифода аз оператор==
- барои майдонҳои истинод шумо бояд усули онҳоро даъват кунед
equals
- барои массивҳо, шумо метавонед итератсияи даврӣ ё усулро истифода баред
Arrays.equals()
- барои намудхо
float
ваdouble
истифода бурдани усулхои мукоисаи синфхои муво-фики парпечFloat.compare()
ваDouble.compare()
- барои намудҳои ибтидоӣ (ба истиснои
- Ва ниҳоят, ба се савол ҷавоб диҳед: оё усули татбиқшуда симметрӣ аст ? гузаранда ? розй шудед ? Ду принсипи дигар ( рефлексивӣ ва итминон ) одатан ба таври худкор иҷро карда мешаванд.
Қоидаҳои бекоркунии HashCode
Хэш рақамест, ки аз an object тавлид шудааст, ки ҳолати онро дар ягон лаҳза тавсиф мекунад. Ин рақам дар Java асосан дар ҷадвалҳои ҳаш ба монандиHashMap
. Дар ин ҳолат, функсияи хэшии ба даст овардани адад дар асоси an object бояд тавре амалӣ карда шавад, ки тақсимоти нисбатан баробари элементҳо дар саросари ҷадвали hash таъмин карда шавад. Ва инчунин барои кам кардани эҳтимолияти бархӯрд, вақте ки функсия як арзишро барои калидҳои гуногун бармегардонад.
hashCode шартнома
Барои амалисозии функсияи hash, мушаххасоти забон қоидаҳои зеринро муайян мекунад:- як ё якчанд маротиба даъват кардани усул
hashCode
дар ҳамон an object бояд ҳамон арзиши хэшро баргардонад, ба шарте ки майдонҳои an object дар ҳисобкунии арзиш тағир наёфта бошанд. - даъват кардани усул
hashCode
дар ду an object бояд ҳамеша як рақамро баргардонад, агар an objectҳо баробар бошанд (даъват кардани усулequals
дар ин an objectҳо бармегардадtrue
). - даъват кардани усул
hashCode
дар ду an objectи нобаробар бояд арзишҳои гуногуни hash баргардонад. Гарчанде ки ин талабот ҳатмӣ нест, бояд ба назар гирифт, ки татбиқи он ба иҷрои ҷадвалҳои ҳаш таъсири мусбат мерасонад.
Усулҳои баробар ва hashCode бояд якҷоя бекор карда шаванд
Бар асоси шартномаҳои дар боло тавсифшуда, аз ин бармеояд, ки ҳангоми бекор кардани усул дар codeи худequals
, шумо бояд ҳамеша методро бекор кунед hashCode
. Азбаски воқеан ду мисоли синф аз он сабаб фарқ мекунанд, ки онҳо дар минтақаҳои гуногуни хотира ҷойгиранд, онҳо бояд мувофиқи баъзе меъёрҳои мантиқӣ муқоиса карда шаванд. Мутаносибан, ду an objectи аз ҷиҳати мантиқӣ баробар бояд арзиши якхелаи хешро баргардонанд. Агар танҳо яке аз ин усулҳо бекор карда шавад, чӣ мешавад?
-
equals
ҲаhashCode
НеФарз мекунем, ки мо методро
equals
дар синфи худ дуруст муайян кардем ваhashCode
қарор додем, ки усулро ҳамон тавре ки дар синф аст, тарк кунемObject
. Он гоҳ аз нуқтаи назари усулequals
ду an object аз ҷиҳати мантиқӣ баробар хоҳанд буд, дар ҳоле ки аз нуқтаи назари усулhashCode
онҳо ҳеҷ чизи умумӣ надоранд. Ва ҳамин тавр, бо ҷойгир кардани an object дар ҷадвали ҳаш, мо хатари онро ба даст наовардани онро бо калид дорем.
Масалан, ба ин монанд:Map<Point, String> m = new HashMap<>(); m.put(new Point(1, 1), “Point A”); // pointName == null String pointName = m.get(new Point(1, 1));
Аён аст, ки an objectи ҷойгиршуда ва an objectи ҷустуҷӯшаванда ду an objectи гуногун мебошанд, гарчанде ки онҳо аз ҷиҳати мантиқӣ баробаранд. Аммо, зеро онҳо арзишҳои гуногуни хэш доранд, зеро мо шартномаро вайрон кардем, мо гуфта метавонем, ки мо an objectи худро дар ҷое дар дохor ҷадвали ҳаш гум кардем.
-
hashCode
Ҳаequals
Не.Чӣ мешавад, агар мо усулро бекор кунем
hashCode
ваequals
татбиқи усулро аз синф мерос гиремObject
. Тавре ки шумо медонед,equals
усули пешфарз танҳо нишондиҳандаҳоро бо an objectҳо муқоиса карда, муайян мекунад, ки оё онҳо ба як an object ишора мекунанд. Фарз мекунем, киhashCode
мо усулро мувофиқи ҳама қонунҳо навиштаем, яъне онро бо истифода аз IDE тавлид кардем ва он ҳамон арзишҳои хэшро барои an objectҳои мантиқии якхела бармегардонад. Аён аст, ки бо ин кор мо аллакай ягон механизми мукоисаи ду an objectро муайян кардем.Аз ин рӯ, мисоли параграфи қаблӣ бояд аз ҷиҳати назариявӣ иҷро карда шавад. Аммо мо то ҳол an objectи худро дар ҷадвали ҳаш ёфта наметавонем. Гарчанде ки мо ба ин наздик хоҳем буд, зеро ҳадди аққал мо як сабади мизи ҳашро пайдо хоҳем кард, ки дар он an object хобида хоҳад буд.
Барои бомуваффақият ҷустуҷӯ кардани an object дар ҷадвали hash, ба ғайр аз муқоисаи қимматҳои хеши калид, муайян кардани баробарии мантиқии калид бо an objectи ҷустуҷӯшуда низ истифода мешавад. Ин аст, ки
equals
бидуни аз эътибор соқит кардани усул ҳеҷ роҳе нест.
Алгоритми умумӣ барои муайян кардани hashCode
Дар ин ҷо, ба назарам, шумо набояд аз ҳад зиёд хавотир шавед ва усулро дар IDE дӯстдоштаи худ эҷод кунед. Азбаски ҳамаи ин тағирёбии битҳо ба рост ва чап дар ҷустуҷӯи таносуби тиллоӣ, яъне тақсимоти муқаррарӣ - ин барои дугонаҳои комилан якрав аст. Шахсан ман шубҳа дорам, ки ман метавонам беҳтар ва зудтар аз ҳамон Идея кор кунам.Ба ҷои хулоса
Ҳамин тариқ, мо мебинем, ки усулҳо дар забони Java нақши дақиқequals
доранд ва барои ба даст овардани баробарии мантиқии ду an object тарҳрезӣ шудаанд. hashCode
Дар мавриди усул, equals
ин ба муқоисаи an objectҳо робитаи мустақим дорад, дар сурати hashCode
ғайримустақим, вақте ки лозим аст, бигӯем, ки ҷойгиршавии тақрибии an objectро дар ҷадвалҳои ҳеш ё сохторҳои шабеҳи додаҳо муайян кунед, то суръати чустучуи an objectро баланд бардоранд. Ба гайр аз шартномахо боз як талаби марбут ба мукоисаи an objectхо мавчуд аст equals
. hashCode
Ин мувофиқати усули compareTo
интерфейс Comparable
бо equals
. Ин талабот таҳиякунандаро вазифадор мекунад, ки ҳамеша x.equals(y) == true
ҳангоми x.compareTo(y) == 0
. Яъне мо мебинем, ки муќоисаи мантиќии ду an object набояд дар њељ љои замима мухолиф бошад ва њамеша пайваста бошад.
GO TO FULL VERSION