CopyOnWriteArrayList 扩容为什么只+1?

2019-04-08 15:42:50 +08:00
 c4f36e5766583218

https://blog.csdn.net/silyvin/article/details/79407034

网上只搜到这个,看不懂~~~没说清 why

2487 次点击
所在节点    Java
8 条回复
c4f36e5766583218
2019-04-08 15:51:51 +08:00
比如为啥不像```java. util.ArrayList```涨 1.5 倍这样?
BBCCBB
2019-04-08 15:52:39 +08:00
每次 Write 时都要 Copy, 除了 addAll 这种 add 多个的, 没必要+n。 扩容+n,多的那部分用不到。
joshryo
2019-04-08 16:36:17 +08:00
这个集合在 add 动作前都会拷贝一份原集合,并在原集合的基础上+1,多出来的一个就是为了放置新的那个元素...addAll 的时候就不是+1 了
c4f36e5766583218
2019-04-08 17:04:58 +08:00
@BBCCBB #2
@joshryo #3
java.util.concurrent.CopyOnWriteArrayList#add(E),就拿这个方法来说(为什么不按 ArrayList 原理实现?)
.add("a") // 内部判断```Object[] array```是否够放,不够放就扩容 1.5 倍( copy 了)
.add("b") // ```Object[] array```够放了(不用 copy ),直接在对应的 index 处设值
------
ArrayList 有
```transient Object[] elementData;```
```private int size;```
通过 size 来标记 elementData 用到了哪个下标。。
------
你俩说的,我还是没 get 到 why。
会不会是 CopyOnWriteArrayList 内如果添加 size 字段,但没法保证 size 的并发?
BBCCBB
2019-04-08 17:08:01 +08:00
。。。
照你说的,现在是 16,扩容 1.5 倍就是 24, 但是现在只是添加一个元素,size=17, 那 24-17=7 个元素就被浪费掉了,根本用不到,因为下次执行修改操作的时候这个数组就没用了,会新分配一个数组,将原数组的数据拷贝过来
hujianxin
2019-04-08 17:27:26 +08:00
如果是单纯 add 的话,语意就是+1,为什么要 1.5 倍呢,关键是 add 与扩容不是一个概念

话说回来,既然每次 add 都要扩容 1 了,就没有必要再另外进行 1.5 倍的扩容了。

感觉 copyonwritearraylist 在牺牲一些 copy 过程的性能,来换取读写分离的方便。因为,如果你有两个线程,一个通过迭代器读,另一个写,这样会导致 ConcurrentModificationException,为了避免这个,普通 arraylist 需要对整个 list 加锁,这样损失的性能比 copy 损失的性能来的更多。

归根结底,还得看应用场景
geelaw
2019-04-08 17:41:38 +08:00
COWAL 是只读数组,所以不需要有任何多余的容量。
c4f36e5766583218
2019-04-08 20:04:35 +08:00
@BBCCBB #5 哦,对对,我想错了,是你说的```会新分配一个数组```
此贴终结。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/552987

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX