为什么Java集合中的contains()/ indexOf()使用o.equals(e)而不是e.equals(o)?

时间:2010-05-27 15:38:55

标签: java collections equals

为什么Java集合框架中的方法contains()indexOf()使用o.equals(e)而不是e.equals(o)定义(其中o是方法的参数并且e是集合中的元素)?

有人知道原因吗?

3 个答案:

答案 0 :(得分:16)

因为已知o不为空,但e不一定是。以LinkedList

的代码为例
for (Entry e = header.next; e != header; e = e.next) {
    if (o.equals(e.element))
        return index;
    index++;
}

在此示例中,以这种方式执行此操作可避免为集合中的每个项目保护e.element为空。这是考虑o为空的完整代码:

if (o == null) {
    for (Entry e = header.next; e != header; e = e.next) {
        if (e.element == null)
            return index;
        index++;
    }
} else {
    for (Entry e = header.next; e != header; e = e.next) {
        if (o.equals(e.element))
            return index;
        index++;
    }
}

答案 1 :(得分:1)

使用x.equals(y)y.equals(x)之间的区别如下:

如果xnull,则y.equals(x)只会返回false whyle x.equals(y)会导致NullPointerException。

答案 2 :(得分:1)

假设您有一组友好对象,例如

class Friendly {
    final int i;
    Friendly( int i ) { this.i = i; }
    public boolean equals( Object o ) {
        return o != null && o instanceof Friendly && ((Friendly)o).i == this.i;
    }
}

java.util.Collection c = new java.util.ArrayList();
for( int i = 0; i < 10; i++ )
    c.add( new Friendly(i) );

并且您希望插入一个不友好的对象,contains永远不会在集合中找到它:

class Unfriendly extends Friendly {
    Unfriendly( int i ) { super(i); }
    public boolean equals( Object o ) { return false; }
}

如果contains调用e.equals(o),那么您的险恶计划将失败,因为集合中已有的友好元素决定是否不友好对象等于或不等。 通过调用o.equals(e),传递给contains不友好对象可以决定它想要的内容,允许您使用方法覆盖功能。< / p>

System.out.println("contains friendly? " + c.contains(new Friendly(1)));
#> contains friendly? true
System.out.println("contains unfriendly? " + c.contains(new Unfriendly(1)));
#> contains unfriendly? false

contains friendly?true,因为我们正在使用ArrayList;如果我们使用HashSet或任何哈希值,则有必要指定hashCode方法。

请注意,虽然contains的合同要求使用equals方法,但某些实现可能不符合此类,例如org.eclipse.emf.common.util.BasicEList,因为您想到这一点而浪费时间进行。

在这种情况下,您必须自己进行比较,例如

boolean contained = false;
for( Object e : c )
    if( o.equals(e) ) { contained = true; break; }