第108集:容器equals和hashcodeJDK源代码分析
本集知识点
Java中规定,若两个对象equals比较后内容相等(为true),则hashCode必须相等,反之不然。【原因见内存分析图】
hashCode与equals方法必须同时重写,且必须保证第一点。
父类Object的hashCode()是用内存地址计算,而equals比较的是它是否是同一个对象。
package com.collection;public class Student {private int id;private String name;@Overridepublic int hashCode() {final int prime = 31;//这里一般取质数,做个散列算法,让值分布均匀int result = 1;result = prime * result + id;result = prime * result + ((name == null) ? 0 : name.hashCode());return result;}@Overridepublic boolean equals(Object obj) {if (this == obj)return true;if (obj == null)return false;if (getClass() != obj.getClass())return false;Student other = (Student) obj;if (id != other.id)return false;if (name == null) {if (other.name != null)return false;} else if (!name.equals(other.name))return false;return true;}}
package com.collection;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;public class TestEquals {public static void main(String[] args){List list = new ArrayList();String s1 = "aaa";String s2 = "aaa";list.add(s1);list.add(s2);System.out.println(list.size());Map map = new HashMap();map.put(s1, "ccc");map.put(s2, "ssss");System.out.println(map.get(s1));}
}
第109集:容器ListMap底层源码再分析bug解决
两个细节的改进
改进遍历的效率——可以先与中间的数比较,然后决定从前面还是后面开始找。
hashcode可能返回负值
public Node node(int index){Node temp = null;if(first!=null){if(index < (size>>1)){temp = first;for(int i=0;i<index;i++){temp = temp.next;}} else {temp = last;for(int i=size-1;i>index;i--){temp = temp.next;}}}return temp;}
package com.collection;import java.util.LinkedList;public class SxtMap002 {LinkedList[] arr = new LinkedList[999];int size;public void put(Object key,Object value){SxtEntry e = new SxtEntry(key,value);int hash = key.hashCode();hash = hash<0?-hash:hash;int a = hash%arr.length;if(arr[a]==null){LinkedList list = new LinkedList();arr[a] = list;list.add(e);} else {LinkedList list = arr[a];for(int i=0;i<list.size();i++){SxtEntry e2 = (SxtEntry)list.get(i);if(e2.key.equals(key)){e2.value=value;//键值重复直接覆盖。return;}}arr[a].add(e);}}
}