Java AbstractCollection为什么不实现size()?
当对AbstractCollection进行子分类时,我仍然必须实现Java AbstractCollection为什么不实现size()?,java,collections,size,Java,Collections,Size,当对AbstractCollection进行子分类时,我仍然必须实现size(),即使(我相信)有一个合理正确(尽管没有性能)的默认实现: public int size() { int count = 0; for (Iterator<E> i = iterator(); i.hasNext();) { i.next(); count++ } return count; } public int size(){
size()
,即使(我相信)有一个合理正确(尽管没有性能)的默认实现:
public int size() {
int count = 0;
for (Iterator<E> i = iterator(); i.hasNext();) {
i.next();
count++
}
return count;
}
public int size(){
整数计数=0;
for(迭代器i=Iterator();i.hasNext();){
i、 next();
计数++
}
返回计数;
}
为什么设计人员没有包含
size()
的默认实现?他们是否试图强迫开发人员有意识地考虑这种方法,希望让开发人员提供一种性能优于默认值的实现?我怀疑您的最后一句话是真正的原因。当对抽象类进行子类化时,有时只会覆盖抽象方法。我希望几乎每个实现都有一个比迭代更好的实现——因此,如果您希望几乎每个人都重写一个方法,那么最好不要提供基本(缓慢)实现。它只是减少了出错的机会:)虽然这是一个可能的默认实现,但它不一定是一个好的实现(甚至不是一个正常的实现)
在几乎所有的通用集合实现中,都有一个O(1)方法来确定大小。通常只需查询一个简单字段
这应该是执行。在极少数情况下,如果不是这样的话,实现仍然可以回到您的示例代码(或者以不同的方式实现)。我支持您的理论:可能实现者只是被迫为size()
实现一个好的(O(1)
,如果可能的话)实现,因为
- 这种方法经常使用
- 如果我们针对接口编程,我们不知道实际的集合类型
- 默认(或错误)实现可能会意外地破坏性能
实际上,由于add
和remove
操作都有一个返回值,指示该操作是否导致集合大小的更改,因此在大多数情况下,通过跟踪添加和删除,您可以更好地实现事件size
方法 对于某些类型的列表,您建议的默认实现是有害的。我想到的是惰性列表,或者迭代时导致内存中数据结构非常大的列表
在无限延迟列表的情况下,您建议的默认实现显然是不正确的。例如,对于ArrayList来说,它不是非常合理的实现。这可能就是为什么他们在默认情况下没有实现它以避免隐藏的陷阱。@denis.solonenko:我的意思是,从正确性的角度来看,它是合理的。我同意你的观点,从性能的角度来看这是不合理的。我所知道的没有一种情况,该方法不会被重写。尽管CLQ接近这一点,但impl速度更快。简单地说:这是一段无用的代码,每次都必须重写它,它会抛出ConcurrentModificationException,在这种情况下,你会怎么做?@bestsss:我同意。我几乎总是提供优于O(N)的实现。我只是好奇,看看人们还能想出什么其他理由@亚当,顺便说一句,如果(++count==Integer.MAX_VALUE)返回count,您需要像一样退出
而不是count++
实际上迭代可以抛出一个concurrentModificationException
,这对于size()
@bestsss()是不可接受的,这是一个运行时异常。。。如果一个集合没有被记录为线程安全的(这是唯一可能出现问题的地方),那么我认为size()抛出ConcurrentModificationException并不可怕。集合框架的所有异常都是运行时异常,但它们都被记录了(包括NPE、ClassCastException、ArrayStoreException等).@bestsss:那么可能应该实际记录size()
,从而可能引发此问题。为什么不可能有一个需要多个操作来计算大小的集合呢?然后是isEmpty()等等。基本上一切都好。我的理解是size()是在尽最大努力的基础上工作的。