在 Guava 中,有一种向ImmutableList
添加或删除项目的有效方法(当然,可以在此过程中创建新列表)。
我想出的最简单的方法是:
private ImmutableList<String> foos = ImmutableList.of();
public void addFoo(final String foo) {
if (this.foos.isEmpty()) {
foos = ImmutableList.of(foo);
} else {
foos = ImmutableList.<String>builder().addAll(foos).add(foo).build();
}
}
public void removeFoo(final String foo) {
final int index = this.foos.indexOf(foo);
if (index > -1) {
final Builder<String> builder = ImmutableList.<String>builder();
if (index > 0) builder.addAll(this.foos.subList(0, index));
final int size = this.foos.size();
if (index < size - 1) builder.addAll(this.foos.subList(index+1, size));
this.foos = builder.build();
}
}
我想避免这样做的是:
public void removeFoo(final String foo) {
final ArrayList<String> tmpList = Lists.newArrayList(this.foos);
if(tmpList.remove(foo))this.foos=ImmutableList.copyOf(tmpList);
}
但不幸的是,它比我能想到的任何仅使用 Guava 的方法都要简单得多。我错过了什么吗?
最佳答案
ConcurrentModificationException
与并发和同步并没有真正的关系。同时访问可变的List
可能会破坏它和/或引发异常(请为所有3种可能性做好准备)。您的代码不能以这种方式失败,但是在多线程中它也不起作用:
foos
是volatile
,则不能保证另一个线程将看到您所做的更改。 volatile
,也可能会丢失一些更改,例如,当两个线程将一个项目添加到foos
时,两个线程都可以从原始值开始,然后最后写入的那个赢(仅添加其项目)。 您要避免的代码是无可避免的。
ImmutableList.Builder
仅涵盖允许以紧凑方式处理它们的最常见情况。 您可能想看看persistent collections,它已针对此类操作进行了优化。但是,您不应期望例如持久列表与
ArrayList
或ImmutableList
一样快。