【147天】尚学堂高淇Java300集视频精华笔记(108-109)
第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); } } }