List.removeAll() 引起的思考

Think It

public static void main(String[] args) {
    	List<String> stringList = Arrays.asList("1", "2");
    	List<Long> longList = Arrays.asList(1L, 2L);
    	longList.removeAll(stringList);
    	System.out.println(longList.toString());
  	}

Summary

不只是個錯誤使用問題,反應本身對這塊的只是庫存不足java

removeAll 方法流程

最終是內存地址相同的時候,才判斷有效(這裏在刪除對象的時候,必須內存地址同樣才能刪除,除非重寫equals方法)面試

public boolean equals(Object obj) {
		return (this == obj);
	}

但若是構造的內容是List<String>,由於String 重寫了equals方法,因此會比較內容,內容相同便可(可是必須是String類型,咱們在上面例子中,刪除的是Long,因此無效)ide

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

重寫equals方法要符合規範

/**
     * Indicates whether some other object is "equal to" this one.
     * <p>
     * The {@code equals} method implements an equivalence relation
     * on non-null object references:
     * <ul>
     * <li>It is <i>reflexive</i>: for any non-null reference value
     *     {@code x}, {@code x.equals(x)} should return
     *     {@code true}.
     * <li>It is <i>symmetric</i>: for any non-null reference values
     *     {@code x} and {@code y}, {@code x.equals(y)}
     *     should return {@code true} if and only if
     *     {@code y.equals(x)} returns {@code true}.
     * <li>It is <i>transitive</i>: for any non-null reference values
     *     {@code x}, {@code y}, and {@code z}, if
     *     {@code x.equals(y)} returns {@code true} and
     *     {@code y.equals(z)} returns {@code true}, then
     *     {@code x.equals(z)} should return {@code true}.
     * <li>It is <i>consistent</i>: for any non-null reference values
     *     {@code x} and {@code y}, multiple invocations of
     *     {@code x.equals(y)} consistently return {@code true}
     *     or consistently return {@code false}, provided no
     *     information used in {@code equals} comparisons on the
     *     objects is modified.
     * <li>For any non-null reference value {@code x},
     *     {@code x.equals(null)} should return {@code false}.
     * </ul>
     * <p>
     * The {@code equals} method for class {@code Object} implements
     * the most discriminating possible equivalence relation on objects;
     * that is, for any non-null reference values {@code x} and
     * {@code y}, this method returns {@code true} if and only
     * if {@code x} and {@code y} refer to the same object
     * ({@code x == y} has the value {@code true}).
     * <p>
     * Note that it is generally necessary to override the {@code hashCode}
     * method whenever this method is overridden, so as to maintain the
     * general contract for the {@code hashCode} method, which states
     * that equal objects must have equal hash codes.
     *
     * @param   obj   the reference object with which to compare.
     * @return  {@code true} if this object is the same as the obj
     *          argument; {@code false} otherwise.
     * @see     #hashCode()
     * @see     java.util.HashMap
     */
    public boolean equals(Object obj) {
        return (this == obj);
    }

翻譯成中文:flex

equals 方法實現的時候必需要知足的特性:

1.(reflexive)自反性:

對於任何非 null 的引用值 x,x.equals(x) 必須爲 true;

2.(symmetric)對稱性: 
對於任何非 null 的引用值 x,y,當且僅當 y.equals(x) 返回 true 時,x.equals(y) 也要返回 true 。

3.(transitive)傳遞性: 
對於任何非 null 的引用值 x,y,z, 若是 x.equals(y) 返回 true,y.equals(z) 返回 true,那麼 x.equals(z) 必定要返回 true。

4.(consistent)一致性: 
對於任何非 null 的引用值 x,y,只要 equals() 方法沒有修改的前提下,屢次調用 x.equals(y) 的返回結果必定是相同的。

5.(non-nullity)非空性 
對於任何非 null 的引用值 x,x.equals(null) 必須返回 false。

覆蓋 equals 時,必定要同時覆蓋 hashCode !!!

這樣作的目的是保證每個 equals()返回 true 的兩個對像,要有兩個相同的 hashCode 。 重寫方法的快捷鍵 command+Nui

in the end

一個在面試的時候,常常被問到的 java 基礎題:this

java 中 == 和 equals 和 hashCode 的區別?
java 中有兩種類型,值類型和引用類型。其中,== 值類型和引用類型均可以運算,equals 和 hashCode 是引用類型特有的方法。

對於值類型,== 比較的是它們的值,對於引用類型,== 比較的是二者在內存中的物理地址。

equals() 是 Object 類中的方法,默認實現是使用 == 比較兩個對象的地址,可是在一些子類,例如 String,Float,Integer 等,它們對 equals進行覆蓋重寫,就再也不是比較兩個對象的地址了。

hashCode() 也是 Object 類的一個方法。返回一個離散的 int 型整數。在集合類操做中使用,爲了提升查詢速度。

當覆蓋 equals() 的時候,必定要同時覆蓋 hashCode(),保證 x.equals(y) 返回爲 true 的時候,x,y 要有相同的 HashCode 。
相關文章
相關標籤/搜索