如果我在这里缺少一些核心Java,请原谅我。
我在HashSet
的javadocs中搜索其实现Collection.containsAll()
的规范,显然它继承了AbstractCollection
的实现,根据JDK 8 source code documentation这个:
public boolean containsAll(Collection<?> c) {
for (Object e : c)
if (!contains(e))
return false;
return true;
}
我的问题源于以下事实:HashSet
不会覆盖containsAll()
,但是会覆盖contains()
:
public boolean contains(Object o) {
return map.containsKey(o);
}
AbstractCollection
同样:
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;
}
我的理解是,当实例中未明确指定实例成员调用时,JVM将其隐式替换为this.instanceMemberCall()
,在这种情况下,它将转换为AbstractCollection
的{{1} }被调用。但是,再I read here,contains()
/ HashMap
的{{1}}的时间复杂度将是O(n),表明HashSet
的{{1} }(O(1))被调用。希望能清楚了解其背后的实际语义是什么。
答案 0 :(得分:3)
不,这仅仅是多态。每当在对象上调用方法时,该对象的 true 类型就无关紧要。
含义:foo()
是在Base中实现的。当foo()
在bar()
被Child覆盖时调用bar()
时。当您有一个Child对象时,它将始终是被调用的Child bar()
版本。
在您的示例中,this
不是AbstractSet,而是HashSet
!
或者换句话说:调用方法的“位置”无关紧要。重要的是调用对象的类型。如前所述,您的对象的类型为HashSet!
答案 1 :(得分:2)
这是一个有趣的问题。 Java中的HashSet
由HashMap
支持。在这种情况下,containsAll()
的contains方法中,contains()
方法只是在HashSet
上循环。这是因为HashSet
会覆盖contains
和委托。
因为HashSet
由HashMap
支持,所以实际的调用是containsKey(Object key)
。
HashMap
的{{1}}主要是给您containsKey(Object key)
的复杂性。但是,O(1)
确实在containsAll()
元素上循环。更糟糕的情况是n
。
我之所以说它主要是 ,是因为O(n)
的性能取决于哈希。