gpt4 book ai didi

java - 在 for 循环中使用迭代器从 ArrayList 中删除元素

转载 作者:行者123 更新时间:2023-11-30 12:05:01 26 4
gpt4 key购买 nike

我有一个包含版本号作为字段的对象的 ArrayList。我想对该 ArrayList 做一些工作,但我只想要该对象的最新版本。我在考虑这样编码:

ArrayList<ObjectVO> ObjectList = getObjectList();
for(ObjectVO myVO : ObjectList) {
Iterator<ObjectVO> iter = ObjectList.iterator();

while(iter.hasNext()) {
ObjectVO checkVO = iter.next();
if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
iter.remove();
}
}
}
}

这有效吗?我不知道我们最初处于 for 循环中的事实是否会在运行时破坏 ArrayList 的可变性。

最佳答案

不,这行不通。 iter.remove() 将导致 out for 循环失败并返回 ConcurrentModificationException

您可以使用带索引的 for 循环和 BitSet 来跟踪要删除的内容,而不是这样做:

BitSet toRemove = new BitSet();
for (int m = 0; m < ObjectList.size(); ++m) {
if (toRemove.get(m)) continue;
ObjectVO myVO = ObjectList.get(m);

for (int c = 0; c < ObjectList.size(); ++c) {
if (toRemove.get(c)) continue;
ObjectVO checkVO = ObjectList.get(c);

if(myVO.getID().equals(checkVO.getID()) {
//they are the same object ID. Check the version number, remove it lower
if(myVO.getVersion() > checkVO.getVersion()) {
toRemove.set(c);
}
}
}
}

这基本上是您的代码,但它还没有执行删除操作。然后您可以扫过列表并删除它们:

int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (!toRemove.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();

像这样使用 BitSet 的要点是,如果您要从末尾以外的任何地方删除,从 ArrayList 中删除是低效的,因为它需要所有的您删除的元素“右侧”的元素将被洗牌一个位置。带有 set/get 和 clear 的循环允许您只移动每个保留的元素一次。


不过,如果您按具有相同 ID 的事物对列表元素进行分组,您可以比二次循环做得更好:那么您就不需要继续检查整个列表:

BitSet toKeep = new BitSet();
IntStream.range(0, ObjectList.size())
.mapToObj(a -> a)
.collect(
groupingBy(a -> ObjectList.get(a).getID(),
maxBy(comparingInt(a -> ObjectList.get(a).getVersion()))))
.values()
.forEach(a -> toKeep.set(a));

int dst = 0;
for (int src = 0; src < ObjectList.size(); ++src) {
if (toKeep.get(src)) {
ObjectList.set(dst++, ObjectList.get(src));
}
}
ObjectList.subList(dst, ObjectList.size()).clear();

关于java - 在 for 循环中使用迭代器从 ArrayList 中删除元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56694171/

26 4 0