首先一HashMap来说
HashMap底层是数组+链表+红黑树
hashcode的作用是算出一串数字和数组长度取模的到数组的存储下标(也就是位置),
Object的hashcode算出来的值都是不一样的,如果是重写后的,同一个对象计算出来的hashcode就是一样的,比如说存一个key到Hashmap中
计算对象的hashcode值,与数组长度取模得到位置如果该位置上有其他对象存在,则该位置延伸出链表,链表不超过8,超过8以红黑树存储。假设该位置上,有一个对象已经存在了,说明hashcode是相同的,那就比较内容equals不同就是两个对象如果相同就是同一个key对象,找到了那如果equals相等,说明你是同一个对象,则hashcode一定相等,因为不同对象算出来的hashcode是不同的
如果你只重写了equals,没有重写hashcode,那查询HashMap时,首先会计算该key对象的hashcode值,取模计算出hash表的位置,由于没有重写hashcode,计算出来的值不一定会和目标key的hash值相同,因此,equals时,会返回null。没有对应结果
因此重写equals,又重写了hashcode时,同一个key对象查找时,计算出来的位置相同,再查找equals时,会找到该key对象结论
hashcode相等,equals不一定是trueequals是true,hashcode一定相等重写了equals,一定会重写hashcode自定义类未重写hashcode和equals时
/** Students类未重写hashcode和equals时 */ Students s1 = new Students("张三",18); Students s2 = new Students("张三",18); Students s3 = new Students("张er",15); System.out.println(s1 == s2);//false System.out.println(s1 == s3);//false System.out.println(s1.equals(s2));//false System.out.println(s1.equals(s3));//false System.out.println(s1.hashCode());//1567581361 System.out.println(s2.hashCode());//849460928 System.out.println(s3.hashCode());//580024961 自定义类只重写了hashcode方法时 equals不相等hashcode相等了,在需要计算hash值的场景,查找元素时很方便 /** Students类未重写hashcode和equals时 */ Students s1 = new Students("张三",18); Students s2 = new Students("张三",18); Students s3 = new Students("张er",15); System.out.println(s1 == s2);//false System.out.println(s1 == s3);//false System.out.println(s1.equals(s2));//false System.out.println(s1.equals(s3));//false System.out.println(s1.hashCode());//24022538 System.out.println(s2.hashCode());//24022538 System.out.println(s3.hashCode());//725572003 重写equals时,没重写hashcode时 只有对象内容是相等了,返回true,hashcode不相等不影响对象内容的比较 /** Students类未重写hashcode和equals时 */ Students s1 = new Students("张三",18); Students s2 = new Students("张三",18); Students s3 = new Students("张er",15); System.out.println(s1 == s2);//false System.out.println(s1 == s3);//false System.out.println(s1.equals(s2));//true System.out.println(s1.equals(s3));//false System.out.println(s1.hashCode());//1567581361 System.out.println(s2.hashCode());//849460928 System.out.println(s3.hashCode());//580024961 重写了两个方法时 相同对象的hashcode计算出来是一样的值比较两个相同对象的内容也是相同的 /** Students类未重写hashcode和equals时 */ Students s1 = new Students("张三",18); Students s2 = new Students("张三",18); Students s3 = new Students("张er",15); System.out.println(s1 == s2);//false System.out.println(s1 == s3);//false System.out.println(s1.equals(s2));//true System.out.println(s1.equals(s3));//false System.out.println(s1.hashCode());//24022538 System.out.println(s2.hashCode());//24022538 System.out.println(s3.hashCode());//725572003自定义类没有重写那俩方法时
map中存入两个我们认为相同的对象然后通过map.get()来获取该对象得到结果是null原因分析:
因为存储时,先计算的是key对象的hashcode值取模计算出来hash值,当做数组的下标然后因为没有重写hashcode,计算出来的是两个位置再次get取我们认为相同的对象时,计算出来的是另一个位置,永远比较不上equals比较时,没得比,得到了空,就认为你没有存这个key对象 Map<Students,Integer> map = new HashMap<>(); map.put(new Students("张思",22),22); map.put(new Students("张思",22),23); map.put(new Students("张思si",22),23); Integer integer = map.get(new Students("张思",22)); System.out.println(integer);//null 重写了equals时,没有重写hashcode 查询结果还是null Map<Students,Integer> map = new HashMap<>(); map.put(new Students("张思",22),22); map.put(new Students("张思",22),23); map.put(new Students("张思si",22),23); Integer integer = map.get(new Students("张思",22)); System.out.println(integer);//null 重写了hashcode没有重写equals null,位置找到是找到了,equals一比还是false Map<Students,Integer> map = new HashMap<>(); map.put(new Students("张思",22),22); map.put(new Students("张思",22),23); map.put(new Students("张思si",22),23); Integer integer = map.get(new Students("张思",22)); System.out.println(integer);//null 当重写了那俩之后 查出来结果是23因为重写了equals和hashcode,因此位置找到了,再比较内容,是true由于key不允许出现重复值,后put的kv对象覆盖前一个kv对象 Map<Students,Integer> map = new HashMap<>(); map.put(new Students("张思",22),22); map.put(new Students("张思",22),23); map.put(new Students("张思si",22),23); Integer integer = map.get(new Students("张思",22)); System.out.println(integer);//23 说的是键不能重复,不是hashcode不能重复,位置和你键是不是重复不能一概而论 不同对象计算出来的hashcode也有相同的,那个位置完全是有可能存储其他类型的键对象的