Java HashSet addAll方法修改类内部字段
我有一个类,它扩展了HashSet的参数化版本。此类有一个内部字段Java HashSet addAll方法修改类内部字段,java,hashset,Java,Hashset,我有一个类,它扩展了HashSet的参数化版本。此类有一个内部字段currentSize,用于跟踪到目前为止添加了多少元素。子类重写基类“add和addAll方法,因此currentSize相应增加。我的问题是在addAll中,集合的大小被添加到currentSize计数器中两次,而不是一次。下面是我的班级代码: public class InheritHashSet extends HashSet<Integer> { private int currentSize = 0
currentSize
,用于跟踪到目前为止添加了多少元素。子类重写基类“add
和addAll
方法,因此currentSize
相应增加。我的问题是在addAll
中,集合的大小被添加到currentSize
计数器中两次,而不是一次。下面是我的班级代码:
public class InheritHashSet extends HashSet<Integer> {
private int currentSize = 0;
@Override
public boolean add(Integer e) {
currentSize++;
super.add(e);
}
@Override
public boolean addAll(Collection<? extends Integer> e) {
currentSize += e.size();
super.addAll(e);
}
public int getCurrentSize() {
return currentSize;
}
}
看起来调用
super.addAll(e)
也会修改currentSize
(这似乎毫无意义) 扩展现有集合类几乎从来都不是一个好主意,特别是当您试图强制执行新契约时
我建议您重新设计类,使其具有HashSet字段,而不是扩展HashSet
阅读第16项:偏爱组合而不是继承。继承hashset的addAll()
方法类第一集currentSize=3,带有currentSize+=e.size()代码>指令。然后super.addAll(e)代码>调用add(e)
方法三次。对于动态绑定,首先调用类InheritHashSet
的public boolean add(整数e)
,然后将currentSize
增加到6
因此,您应该以以下方式实现addAll
方法:
@Override
public boolean addAll(Collection<? extends Integer> e) {
return super.addAll(e);
}
@覆盖
公共布尔addAll(CollectionWhat'ssuper.addAll(e)
do?这正是为什么不应该扩展HashSet,而应该使用HashSet。请注意,currentSize的名称非常糟糕。它根本不是大小。如果是,它将毫无用处,因为HashSet已经有了大小。@jbnize我不知道可以使用HashSet的size()来确定大小
方法,我只是想知道为什么这种计算集合中元素数量的方法不能得到正确的答案。请查看super.addAll
的源代码。它可能在内部调用add
。这就是为什么会重复计算。如果扩展现有实现,则必须查看该实现如何直到HashSet决定不再调用add(),而是通过委托给新的私有doAdd()来实现addAll()方法,这将破坏子类并导致0而不是3。您不应该扩展HashSet。我完全同意,您指出这一点是正确的,但我们不知道OP代码的真正意图。他编写此代码可能只是为了一个简单的测试或研究。他只问为什么会出现这种奇怪的行为,事实并非如此立即意识到。是我忽略了什么,还是这个实现没有用?它只是调用超级方法,而不改变可见性,那么这有什么意义呢?当然,JB Nizet是对的。这很难。是“最干净”还是“最安全”解决方案可能是使用所需集合(HashSet
)实现其size
、iterator
和add
方法的MySpecialSet extends AbstractSet implements Set
)但是我敢打赌,对于询问者真正想要达到的目标,有更优雅的解决方案……我只是从addAll实现中删除了currentSize
增量,因为我注意到这是一个错误。你不知道该方法是否做了其他事情以及OP simplifi编辑它是因为他想专注于currentSize
问题(并且为了创建一个最小的工作示例)。@Sotirios是的,你编辑它是对的。无论如何,我很快就会删除这一行
@Override
public boolean addAll(Collection<? extends Integer> e) {
return super.addAll(e);
}