ورود

View Full Version : سوال: Add کردن هنگام پیمایش ArrayList و ConcurrentModificationException یا استفاده از LinkedList ؟؟؟



vahid-p
سه شنبه 16 اردیبهشت 1393, 20:14 عصر
وقتی که یک ArrayList رو به طریق زیر پیمایش میکنم و در خلال اون به ArrayList اضافه میکنم استثنا از نوع ConcurrentModificationException میده.
for(Production p:prods){
if(p.getLeft()=='c') prods.add(new Production('?',null));
}
چون حین پیمایش به ArrayList اد میکنیم یا حتی حذف میکنیم، اکسپشن میده.
از Iterator که استفاده کنی، remove کار میکنه ولی خب Iterator اد که نداره و اگر هم هنگام استفاده از Iterator و prods.add(...) کنی که باز همون Exception رو میده. از طرفی چون تابع به صورت بازگشتی هی به ArrayList مون اضافه میکنه، فکر میکنم نباید یه ArrayList کمکی استفاده کنم و آخرش کامل به اون Add کنم! ( اینو دقیق نمیدونم فعلا )

به این فکر افتادم خب چه کاریه از ArrayList استفاده کنم، از لینک لیست استفاده میکنم که سایز کل لیست ثابت نیست و به هم لینک شده ( البته arraylist هم ثابت نیست و هنگام add کردن سایزش رو چند برابر میکنه ولی به هر حال مثل آرایست )
ولی برای پیمایش LinkedList خود جاوا اگر از Iterator استفاده کنیم، دوباره امکان add کردن نداریم! مگر اینکه بیام یک LinkedList با وِیژگی هایی که خودم میخوام بسازم. البته تو لینک لیست در صورتی که بنویسم :
while(index<list.size()){
i=list.indexOf(index);
System.out.println(i);
if(i==5){
list.addFirst(50);
}
index++;
}
خروجی :

Size : 10
0
1
2
3
4
5
7
8
9
10
به مشکل بر میخوره ( دلیل استفاده از addFirst این هست که گره های جدیدی که اضافه شدن رو دوباره پردازش نکنه ). مثل اینکه با اضافه کردن به اول لیست، کل index ها رو آپدیت میکنه ( چون 6 رو چاپ نکرد )! ولی خب با add معمولی یا همون addLast مشکلی نداره!

با این وجود شما کدوم رو پیشنهاد میدین؟

vahid-p
چهارشنبه 17 اردیبهشت 1393, 16:32 عصر
خب باز هم خودم باید به جواب میرسیدم کسی راهنمایی که نمیکنه. ولی همیشه اگر سوالی مطرح کردم و به جواب رسیدم، جواب رو مینویسم شاید به درد دیگری بخوره.

روش اول : اینکه تونستم از ArrayList کمکی برای اضافه کردن و حذف کردن استفاده کنم ( اینجوری مشکل پردازش گره های جدید به وجود نمیاد چون لیست پردازش و لیست اضافه شده ها جداست ). اونایی که میخوام اضافه کنم در یک لیست temp ریختم و آخرش ArrayList.addAll(temp) کردم و اونایی که میخواستم حذف کنم ابتدا یک نسخشو تو temp اد میکردم و آخرش ArrayList.remove(temp) رو میزنی و اون آبجکت ها رو حذف میکنه از لیست.

اما راه حل کلی : طبق سرچ هایی که زدم، Iterator امکانات کمی بهتون میده. فقط میتونی لیست رو از اول بخونی و بری جلو و فقط میتونی حذف کنی. اما اگر از ListIterator استفاده کنی میتونی بری جلو، برگردی عقب، میتونی همزمان با پیشمایش گره ها رو حذف یا اضافه کنی بدون هیچ Exception ای و کل این عملیات رو میشه به راحتی انجام داد. کلا متد ها و ابزارهای بیشتری در اختیارتون میذاره.

اما استفاده از لینک لیست اینجا زیاد کاربرد نداره مگر اینکه برای پیمایشش خودت یک کلاس جدید ازش ارث بری کنی و خودت متد مورد نظرت رو implement کنی.