Java 在ArrayList.trimToSize()中,如果实际上没有发生结构更改,为什么modCount会发生碰撞

Java 在ArrayList.trimToSize()中,如果实际上没有发生结构更改,为什么modCount会发生碰撞,java,Java,例如: public void trimToSize() { modCount++; if (size < elementData.length) { elementData = Arrays.copyOf(elementData, size); } } public void trimToSize(){ modCount++; if(大小

例如:

public void trimToSize() {
    modCount++;
    if (size < elementData.length) {
        elementData = Arrays.copyOf(elementData, size);
    }
}
public void trimToSize(){
modCount++;
if(大小<元素数据长度){
elementData=Arrays.copyOf(elementData,size);
}
}
为什么
modCount
增量不在if中

似乎
modCount
统计的是结构修改意图,而不是有效的结构修改。

根据和各种SO问题,modCount用于跟踪可能在迭代过程中同时进行的修改


如果我们假设一个方法在modCount发生更改时会抛出异常,这实际上意味着ArrayList会对该意图做出反应,正如您所说,通知用户有东西试图更改它。

查看
ArrayList
的实现,我不明白为什么
trimToSize()
ensureCapacity()
两个增量
modCount
。即使在实际重新分配
elementData
数组时,它们也不会更改列表的逻辑视图

modCount
用于确保列表上有视图(迭代器、子列表)的对象可以检测到基础列表上的修改(添加、删除、设置)

在单线程环境中,什么场景可以通过调用
ensureCapacity()
使列表上的迭代器失效?因为迭代器存储的逻辑索引在调用
trimToSize()
ensureCapacity()
时不会改变

ensurecapity()
增加
modCount
的一个原因(我根据我对源代码的理解猜测)是因为它被所有
add()
家族方法调用(在
add()
中甚至有一条注释不允许
do
modCount++
,因为它是由
ensurecapity完成的()

我可能错了——这两种方法有可能使迭代器无效——但如果不是这样,一些评论者提出的标记意图修改列表的理由并不成立:

  • trimToSize()
    调整内部数组的大小以删除未使用的插槽。迭代器或子列表从不使用这些插槽,用户/调用者无意修改列表内容。唯一的目的是节省一些内存
  • ensureCapacity()
    的情况完全相同:不可能缩小列表。如果用户调用此方法,则是为了优化,并在添加元素之前进行适当调整

最后,我想进一步说明:当调用这两种方法中的任何一种方法时,用户不应该期望在迭代中出现一些
ConcurrentMdificationException

不知道你想问什么。如果你真的问为什么
modCount
会增加,即使你的
If语句不通过,那是因为se它在
if语句的外部
。看起来问题是关于java.util.ArrayList::trimToSize()的。猜一猜?因为调用它表示您试图修改列表,这反映了一个错误,即使您这次运气好。@Ngx472,在我发表评论后在中编辑。OP询问为什么在jdk源代码中,某些可能修改数据结构的函数在没有修改的情况下也会标记修改。问题是合法的估计。答案肯定是,该标志显示的更多的是意图,而不是实际更改。
trimToSize()
不会更改
列表的逻辑视图,但它确实更改了对
对象[]的引用
存储
列表的元素。因此,必须将其视为结构修改。假设
迭代器.remove()
trimToSize()
同时运行。您可能会遇到以下问题。(1)
数组.copyOf(elementData,size);
中的
trimToSize()
开始。(2)
iterator.remove()
沿一个位置移动数组元素,(3)
trimToSize()
对象[]
替换为(的副本)
remove
之前存在的版本移动了元素。如果您处于多线程环境中,则必须使用synchronized
ArrayList
,例如使用
集合#synchronizedList(…)
。这不允许出现您描述的某些情况。请参阅主题和如何在MT env中使用迭代器。我同意您不应该在多线程环境中使用
ArrayList
,但我的观点是,
ArrayList
如果检测到就是你。拥有
trimToSize()
increase
modCount
并不是绝对必要的,但如果程序员在不应该的时候意外使用
ArrayList
,那么这是一个非常便宜的操作,它会增加发现bug的机会。从这个角度来看,我认为在方法中尽早增加
modCount
是有意义的D