一:使用foreach遍历
在项目使用foreach遍历数据并且在遍历的过程中移除数据,会报错。
集合已修改;可能无法执行枚举操作的异常
原因是在使用foreach进行遍历时,本质上调用的是IEnumerator的MoveNext方法,是每次调用next()方法,都会检查expectedModCount和 ModCount值是否相等,当我们删除元素后,ModCount会改变与expectedModCount值不同,引起报错。
**
二:使用for循环
**
使用for循环遍历:注意这种方法删除集合元素会导致索引前移导致遍历问题。
ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.
原因是在RemoveAt方法中,当移除完元素之后,数组大小发生了变更,并且会将新的元素列表重新进行位置上的对齐。
使用getRange()方法获取数据,在使用移除方法。
try
{
Console.WriteLine("定时器开始计时");
timer1.Enabled = false;
timer1.Stop();
if (m_list.Count >= 15)
{
List<string> my_temp_list = m_list.GetRange(0, 15);
foreach (var item in my_temp_list)
{
m_list.Remove(item);
}
foreach (var item in my_temp_list)
{
Thread.Sleep(100);
}
Console.WriteLine("本次处理的数据是:"+string.Join(",", my_temp_list));
Console.WriteLine("本次剩余的数据是:" + string.Join(",", m_list));
}
else
{
List<string> my_temp_list = m_list.GetRange(0, m_list.Count);
foreach (var item in my_temp_list)
{
m_list.Remove(item);
}
foreach (var item in my_temp_list)
{
Thread.Sleep(100);
}
Console.WriteLine("本次处理的数据是:" + string.Join(",", my_temp_list));
Console.WriteLine("本次剩余的数据是:" + string.Join(",", m_list));
}
if (m_list.Count>0)
{
timer1.Enabled = true;
timer1.Start();
}
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
**
三:多线程操作数据:
**
使用迭代器的iterator.remove()在单线程下是不会报错的,但是在多线程情况下,一个线程修改了集合的modCount导致另外一个线程迭代时modCount与该迭代器的expectedModCount不相等,这也会报异常。
public class RemoveListForThreads implements Runnable {
static List<String> alist = new ArrayList<>();
public static void main(String[] args) {
RemoveListForThreads s = new RemoveListForThreads();
alist.add("a");
alist.add("b");
alist.add("c");
alist.add("d");
BlockingQueue<Runnable> workQueue = new ArrayBlockingQueue<>(2);
ThreadPoolExecutor executor = new ThreadPoolExecutor(5, 10, 1,
TimeUnit.SECONDS, workQueue);
for (int i = 0; i < 5; i++) {
executor.execute(s);
}
executor.shutdown();
}
@Override
public synchronized void run() {
Iterator<String> iterator = alist.iterator();
while (iterator.hasNext()) {
String s = iterator.next();
if (s.equals("c") && Thread.currentThread().getName().equals("pool-1-thread-1")) {
iterator.remove();
System.out.println(Thread.currentThread().getName() + " " + s);
}
System.out.println(Thread.currentThread().getName() + " " + s);
}
System.out.println(alist);
}
}
上面这段代码创建了一个线程池,开启了五个线程,在run方法中遍历并删除“b”元素,如果该方法不加同步锁sychronized,也会抛出异常