我有一个链表,其中每个元素都有键和值(ArrayList<dataStructure>
)。我想合并具有相同键的元素。
Iterator<CElem> oItr = linkedList.iterator();
{
while (oItr.hasNext())
{
CElem outer = oItr.next();
Iterator<CElem> iItr = linkedList.iterator();
{
while (iItr.hasNext())
{
CElem inner = iItr.next();
if (outer.equals(inner))
continue;
if (outer.getKey().equals(inner.getKey()))
{
outer.getValues().addAll(inner.getValues());
iItr.remove();
}
}
}
}
}
虽然我正在使用迭代器,但删除了获得java.util.ConcurrentModificationException
的方法。什么应该改变摆脱这一点。
答案 0 :(得分:2)
您使用其中一个迭代器删除元素,因此其中第二个不知道此删除并且ConcurrentModificationException
被抛出
顺便说一句:
您应该考虑使用some multimap代替具有键值对的列表
答案 1 :(得分:1)
两个迭代器都遍历链表
Iterator<CElem> oItr = linkedList.iterator();
....
Iterator<CElem> iItr = linkedList.iterator();
可能iItr应该是内部数组列表吗?
更新抓住上述答案我误解了这个问题。但挑战是你有两个遍历列表的迭代器,所以当你使用一个迭代器的remove()方法时,另一个仍然会检测到并发修改。
通常,要从列表中删除重复项,您可以通过Set(例如HashSet)运行它们,但这对您不起作用,因为它只是密钥重复,而不是列表的整个成员。
我采取的方法是尝试在单独的列表中查找并捕获重复的密钥及其值,然后合并并删除重复项作为单独的步骤。
答案 2 :(得分:1)
将要删除的元素添加到另一个列表中,然后在该列表中循环以删除这些元素。
或者,使用地图/集。
答案 3 :(得分:0)
问题在于,当您使用iItr.remove()
时,它会修改列表,iItr
对此感到满意,因为它知道发生了哪些更改,但oItr
不是。我可以看到有三种可能的解决方案:
ConcurrentLinkedQueue
- 但请在Lock-Free Concurrent Linked List in Java查看答案,以获取有关此问题的警告)TreeSet
,会自动保存您的商品(但不会保留订单)确保从其中一个中删除后不使用其他迭代器 - 您可以通过切换要删除的元素来执行此操作,即将iItr.remove()
更改为:
oItr.remove();
break;
这会导致删除每个键的第一个实例,而不是后续的键,这可能不是您想要的行为 - 在这种情况下,您可以尝试向后迭代列表。
答案 4 :(得分:0)
这会有用吗?
Iterator<CElem> oItr = linkedList.iterator();
{
while (oItr.hasNext())
{
CElem outer = oItr.next();
Iterator<CElem> iItr = linkedList.iterator();
{
while (iItr.hasNext())
{
CElem inner = iItr.next();
if (outer.equals(inner))
continue;
if (outer.getKey().equals(inner.getKey()))
{
inner.getValues().addAll(outer.getValues());
outer.remove();
break;
}
}
}
}
}