第108集:容器equals和hashcodeJDK源代码分析
本集知识点
Java中规定,若两个对象equals比较后内容相等(为true),则hashCode必须相等,反之不然。【原因见内存分析图】
hashCode与equals方法必须同时重写,且必须保证第一点。
父类Object的hashCode()是用内存地址计算,而equals比较的是它是否是同一个对象。
package com.collection;
public class Student {
private int id;
private String name;
@Override
public int hashCode() {
final int prime = 31;//这里一般取质数,做个散列算法,让值分布均匀
int result = 1;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public 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);
}
}
}