equals()和hashCode()
equals()和hashCode()
String中的equals()和hashCode()
equals():
1.首先比較兩個物件的引用,若引用相同,則返回true
2.判斷anObject是否是String型別,如果是,將兩個字串轉為位元組陣列逐位元組進行比對,始終相同返回true,有一個位元組不同返回false
3.返回false
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
hashCode():
如果hash值等於0並且字元陣列長度大於0,計算hash值。hash值計算方法為逐字元陣列計算字元值加hash值得31倍
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) {
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i];
}
hash = h;
}
return h;
}
ArrayList和LinkedList中的equals()和hashCode()
ArrayList和LinkedList繼承自java.util.AbstractList,ArrayList和LinkedList中並沒有實現equals()和hashCode(),而是繼承了父類的實現方法
equals()
1.判斷兩個集合的引用是否相同,如果相同則返回true
2.判斷o是否是一個List集合,如果不是返回false
3.生成兩個物件的迭代器,逐個比較物件:如果o1等於空判斷o2是否為空,如果不是,返回false;如果o1不為空且o1不等於o2,返回false
4.如果兩個集合的物件長度不等,返回false
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof List))
return false;
ListIterator<E> e1 = listIterator();
ListIterator<?> e2 = ((List<?>) o).listIterator();
while (e1.hasNext() && e2.hasNext()) {
E o1 = e1.next();
Object o2 = e2.next();
if (!(o1==null ? o2==null : o1.equals(o2)))
return false;
}
return !(e1.hasNext() || e2.hasNext());
}
hashCode()
1.預設hash值為1
2.逐物件計算hash值:hash值等於原來的hash的31倍加此次物件的hash值,此次物件為空時該hash值為0
public int hashCode() {
int hashCode = 1;
for (E e : this)
hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
return hashCode;
}
HashSet和TreeSet中的equals()和hashCode()
HashSet和TreeSet繼承自java.util.AbstractSet,HashSet和TreeSet中並沒有實現equals()和hashCode(),而是繼承了父類的實現方法
equals()
1.如果兩個集合的引用相同,則返回true
2.如果o不是一個Set集合,返回false
3.如果兩個集合的長度不同,返回false
4.如果呼叫方法的集合全部包含o,返回true,否則返回false(這裡有必要看一下containsAll())的實現(見下文)
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Set))
return false;
Collection<?> c = (Collection<?>) o;
if (c.size() != size())
return false;
try {
return containsAll(c);
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
}
containsAll()
可以看到,containsAll()方法進行比對時,是按照o的長度進行比對的。equals()方法在進行呼叫containsAll()方法時,已在前面進行過兩個集合長度的判斷
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
public boolean contains(Object o) {
Iterator<E> it = iterator();
if (o==null) {
while (it.hasNext())
if (it.next()==null)
return true;
} else {
while (it.hasNext())
if (o.equals(it.next()))
return true;
}
return false;
}
hashCode()
Set集合進行hash計算的方式和List集合有些不同,Set集合進行hash計算只是單純的逐物件累加每個物件的hash值,hash值預設為0
public int hashCode() {
int h = 0;
Iterator<E> i = iterator();
while (i.hasNext()) {
E obj = i.next();
if (obj != null)
h += obj.hashCode();
}
return h;
}
HashMap中的equals()和hashCode()
HashMap繼承自java.util.AbstractMap,其中的equals()和hashCode()方法也是由父類實現
equals()
1.判斷兩個集合的引用值是否相同,相同返回true
2.判斷o是否是一個Map集合,不是返回false
3.判斷兩個集合長度是否相等,不等返回false
4.將呼叫equals()方法的集合轉為Set集合後遍歷,如果該key對應的value為空,則判斷o中是否包含該key且key對應的值是否為空;如果該key對應的value值不為空,則判斷o中相同key對應的value值是否相等
public boolean equals(Object o) {
if (o == this)
return true;
if (!(o instanceof Map))
return false;
Map<?,?> m = (Map<?,?>) o;
if (m.size() != size())
return false;
try {
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext()) {
Entry<K,V> e = i.next();
K key = e.getKey();
V value = e.getValue();
if (value == null) {
if (!(m.get(key)==null && m.containsKey(key)))
return false;
} else {
if (!value.equals(m.get(key)))
return false;
}
}
} catch (ClassCastException unused) {
return false;
} catch (NullPointerException unused) {
return false;
}
return true;
}
hashCode()
將集合轉為Set集合後逐物件計算hash值,hash值初始值為0
public int hashCode() {
int h = 0;
Iterator<Entry<K,V>> i = entrySet().iterator();
while (i.hasNext())
h += i.next().hashCode();
return h;
}