1. 程式人生 > >equals()和hashCode()

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;
    }