当前位置:网站首页>(mandatory) override equals must override hashcode (principle analysis)
(mandatory) override equals must override hashcode (principle analysis)
2022-07-24 17:41:00 【Hua Weiyun】
hashCode and equals
hashCode and equals Used to identify objects , The two methods work together to determine whether two objects are equal . as everyone knows , Hash the data according to the generated hash , It can make accessing elements faster . Object by calling Object.hashCode() Generate hash value ; Because hash value conflicts are inevitable The situation of , So when hashCode Phase at the same time , It needs to be called again equals Make a value comparison ; But if hashCode Different , Will directly determine Object Different , skip equals, This accelerates the efficiency of conflict handling .Object In the class definition hashCode and equals Requirements are as follows :
(1) If I have two objects equals The results are equal , Then two objects of hashCode The return value result of must also be the same .
(2) Overwrite at any time equals, Must be overwritten at the same time hashCode.
stay Map and Set Collection , When using these two methods , First judgement hashCode Value , If hash equal , Then judge again equals Result ,HashMap Of get The judging code is as follows
if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k)))){ return (e = getNode(hash(key), key)) ==null ? null :e.value;}if In the conditional expression e.hash == hash It's a prerequisite , Only equality can be executed && The latter part . If it's not equal , be && hinder equals It won't be enforced at all .equals Inequality is not mandatory hashCode It's not equal , But an excellent hash algorithm should try to make the elements evenly distributed , Reduce the probability of conflict , That is to say equals When they are not equal hashCode It's not equal , such && or || Once the short-circuit operation takes effect , It will greatly improve the execution efficiency of the program . If the custom object is Map Key , Then you have to overwrite hashCode and equals. Besides , because Set Stored are non repeatable objects . basis hashCode and equals Judge , therefore Set The stored custom object must also override these two methods . At this time, if you overwrite equals, Without overwriting hashCode, What impact will it have , Let's have a deep experience through the following code :
public class EqualsObject{ privite int id; privite String name; public EqualsObject(int id, String name){ this.id = id; this.name = name; } @Override public boolean equals(Object obj){ // If null, Or not of the same kind , Then return directly false( First of all ) if (obj == null || this.getClass() != obj.class()){ return false; } // If the reference points to the same object , Then return to true if(this == obj){ return true; } // Need to cast to get EqualsObject Methods EqualsObject temp = (EqualsObject)obj; // The criterion of this example is that the values of two attributes are equal , Logic varies with business scenarios if (temp.getId() == this.id && name.equals(temp.getName())){ return true; } return false; }}The first explanation : First, judge whether the types of the two objects are the same , If it doesn't match, it will directly return false. Use here getClass The way , Is strictly limited to only EqualsObject The object itself can execute equals operation .
There is no override hashCode, Then put this object in Set Go to the assembly :
Set<EqualsObject> hashSet = new HashSet<>();EqualsObject a = new EqualsObject(1,"one");EqualsObject b = new EqualsObject(1,"one");EqualsObject c = new EqualsObject(1,"one");hashSet.add(a);hashSet.add(b);hashSet.add(c);System.out.println(hashSet.size());The output is 3,. Although these objects are obviously the same , But in HashSet In operation , There should be only one left , Why did it turn out to be 3 Well ? Because if you don't overwrite hashCode(), Even if equals() Equality is meaningless ,Object.hashCode() The implementation of is to generate different for each object by default int value , It is itself Native Method , Generally, it is related to the memory address of the object . See below C++ Source code implementation :
VM_ENTRY(jint, JVM_IHashCode(JNIEnv* env,jobject handle)) JVMWrapper("JVM_IHashCode"); return handle == NULL ? 0 : objectSynchronizer::FashHashCode (THREAN,JNIHandles::resolve_non_null(handle));VM_ENDObjectSynchronizer The core code is as follows , It is also confirmed from the perspective of code analysis hashCode It is calculated according to the address of the object int Type numeric :
mark = monitor->header();assert(mark->is_neutral(),"invariant");hash = mark->hash();intptr_t hash() const{ return mask_bits(value() >> hash_shift, hash_mask);}because EqualsObject There is no override hashCode, So we get a unique value related to the address of the object , Go back to the HashSet On the set , If you want to store non repeating elements , So you need to EqualsObject Override in class hashCode();
@Overridepublic int hashCode(){ return id + name.hashCode();}EqualsObject Of name The attribute is String type ,String Overwrite the hashCode(), So you can call .equals() The implementation of is related to the specific logic of the class , But each department is the same , Therefore, we should try to analyze the source code to determine its judgment results , For example, the following code :
public class ListEquals(){ public static void main(String[] args){ LinkedList<Integer> linkedList = new LinkedList<Integer>(); linkedList.add(1); ArrayList<Integer> arrayList = new ArrayList<Integer>(); arrayList.add(1); if (arrayList.equals(linkedList)){ System.out.println("equals is true"); } else { System.out.println("equals is false"); } }}Two different collection classes , The output is zero equals is true. because ArrayList Of equals() Only whether it is List Judgment of subclasses , Then called equalsRange() Method :
boolean equalsRange(List<?> other,int form,int to){ final Object[] es = elementData; // use var Variables accept linkedList The traverser of ( First of all ) var oit = other.iterator(); for(; form < to; form++){ // If linkedList There is no element , be equals The result is directly false; // If linkList There are elements , Then compare the values of the corresponding subscripts ( The second place ) if (!oit.hasNext() || !Objects.equals(es[form], oit.next())){ return false; } } // If ArrayList Has traversed , and linkList And the elements , be equals The result is false return !oit.hasNext;}The first explanation : Local variable type inference (Local Variable Type Inference) yes JDK10 Introduced variable naming mechanism , A change Java It is the traditional image of strongly typed language , This is a Java Committed to the future with small size 、 New language features for productivity , Grammar rules that reduce redundancies , Of course, this is just a grammar sugar ,Java It's still a static language . In the initialization phase , Processing var Variable time , The compiler will detect the return type of the code on the right , And use its type for the left , As shown below :
var a = "String";// Output :class java.lang.StringSystem.out.println(a.getClass());var b = Integer.valueOf(7);// Output :class java.lang.IntegerSystem.out.println(b.getClass());// Compilation error . Although it is var, But there are still type restrictions b = 3.0;b In the first assignment , The type is inferred as Integer, So the second assignment is double Error compiling . If a method is used frequently var, Will greatly reduce readability , It's a trade-off , Recommended for use var When defining variables , Try not to exceed two .
The second explanation : Try to avoid calling through instance object references equals Method , Otherwise, it is easy to throw null pointer exceptions . Recommended JDK7 Introduced Objects Of equals Method , Source code is as follows , Can effectively prevent equals Generated on call NPE problem :
public static boolean equals(Object a,Object b){ return (a==b) || (a != null && a.equals(b));}边栏推荐
- Openlayers: point aggregation effect
- Preliminary study of Oracle pl/sql
- Hcip day 3
- 生信常用分析图形绘制02 -- 解锁火山图真谛!
- 通道的分离与合并
- 面会菜评论分析
- Tensorflow introductory tutorial (40) -- acunet
- Separation and merging of channels
- Review and analysis of noodle dishes
- 2022 Yangtze River Delta industrial automation exhibition will be held in Nanjing International Exhibition Center in October
猜你喜欢

The results of the second quarter online moving people selection of "China Internet · moving 2022" were announced

Hcip day 3

C language custom type explanation - structure

Getaverse, a distant bridge to Web3

C language programming training topics: K characters in left-handed string, little Lele and Euclidean, printing arrow pattern, civil servant interview, poplar matrix

电脑监控是真的吗?4个实验一探究竟

Portfwd port forwarding

C language custom type explanation - Consortium

Logical operation of image pixels

Atcoder beginer 202 e - count descendants (heuristic merge on heavy chain split tree for offline query)
随机推荐
The results of the second quarter online moving people selection of "China Internet · moving 2022" were announced
Common questions of testers during interview
Use Matplotlib to simulate linear regression
2022 牛客暑期多校 K - Link with Bracket Sequence I(线性dp)
Preliminary understanding of redis
Class bytecode file
Extension of ES6 function
Socat port forwarding
Preliminary study of Oracle pl/sql
启发式合并(含一般式、树上启发式合并 例题)
Review and analysis of noodle dishes
es(1)
[how to optimize her] teach you how to locate unreasonable SQL? And optimize her~~~
2022 Yangtze River Delta industrial automation exhibition will be held in Nanjing International Exhibition Center in October
Nearly 30 colleges and universities were named and praised by the Ministry of education!
[waiting for insurance] what does waiting for insurance rectification mean? What are the rectification contents?
NC port forwarding
Js实现继承的六种方式
List of stringutils and string methods
通道的分离与合并