我一直从Firebase收到此ConcurrentModificationException
Exception java.util.ConcurrentModificationException:
java.util.ArrayList$ArrayListIterator.next (ArrayList.java:573)
我没有办法解决此问题。我已经在代码中尝试了很多更改。根据Firebase的说法,此行发生了异常:
for (Show show : entityListLanguages) { }
我已经多次更改了代码(例如在循环外部使用“ addAll”等),但仍然收到该错误。现在我不知道该如何解决此问题。
这是我当前的代码:
List<Show> entityListLanguages = movieTheatreShowtimesListItemRecyclerViewAdapter.getShowList(); // This just returns a list, no special thread of background process
movieLanguageList = new ArrayList<>();
availableLanguages.clear();
for (Show show : entityListLanguages) {
MovieLanguage movieLanguage = new MovieLanguage();
movieLanguage.setId(show.getSpokenLanguage());
movieLanguage.setName(show.getSpokenLanguageFormatted());
if (!movieLanguageList.contains(movieLanguage)) {
movieLanguage.setMovieCount(1);
movieLanguageList.add(movieLanguage);
}
}
availableLanguages.addAll(movieLanguageList);
我能想到的唯一可能导致问题的行是:
movieLanguageList.add(movieLanguage);
但是再说一次,我不知道该怎么解决。
我想念什么吗?感谢您的提示。
完整的堆栈跟踪:
java.util.ArrayList$ArrayListIterator.next (ArrayList.java:573)
ch.cineman.ShowtimesFragmentHelper.updateAvailableLanguages (ShowtimesFragmentHelper.java:381)
ch.cineman.ShowtimesFragmentHelper.updateAvailableGenres (ShowtimesFragmentHelper.java:370)
ch.cineman.ShowtimesByMovieFragment$6$1.onListViewUpdated (ShowtimesByMovieFragment.java:301)
ch.cineman.MovieTheatreShowtimesListItemRecyclerViewAdapter$4$3.run (MovieTheatreShowtimesListItemRecyclerViewAdapter.java:569)
android.os.Handler.handleCallback (Handler.java:739)
android.os.Handler.dispatchMessage (Handler.java:95)
android.os.Looper.loop (Looper.java:158)
android.app.ActivityThread.main (ActivityThread.java:7224)
java.lang.reflect.Method.invoke (Method.java)
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run (ZygoteInit.java:1230)
com.android.internal.os.ZygoteInit.main (ZygoteInit.java:1120)
以及更多扩展的代码段:
注意:在代码中的其他任何地方都没有修改EntityListLanguages和entityListGenres。
private List<Show> entityListGenres;
private List<Show> entityListLanguages;
protected MovieTheatreShowtimesListItemRecyclerViewAdapter movieTheatreShowtimesListItemRecyclerViewAdapter;
/**
* Helper method
*/
protected void updateAvailableGenres() {
entityListGenres = movieTheatreShowtimesListItemRecyclerViewAdapter.getShowList();
listedMovies = new ArrayList<>();
movieGenreList = new ArrayList<>();
availableGenres.clear();
for (Show show : entityListGenres) {
Movie movieX = show.getMovie();
if (movieX != null) {
if (!listedMovies.contains(movieX)) {
listedMovies.add(movieX);
}
}
}
for (Movie listedMovie : listedMovies) {
if (listedMovie.getGenres() != null && listedMovie.getGenres().size() > 0) {
for (MovieGenre movieGenre : listedMovie.getGenres()) {
if (!movieGenreList.contains(movieGenre)) {
movieGenre.setMovieCount(1);
movieGenreList.add(movieGenre);
}
}
}
}
availableGenres.addAll(movieGenreList);
CinemanApplication.getCurrentAppInstance().setAvailableGenres(availableGenres);
updateAvailableLanguages();
}
/**
* Helper method
*/
protected void updateAvailableLanguages() {
entityListLanguages = movieTheatreShowtimesListItemRecyclerViewAdapter.getShowList();
movieLanguageList = new ArrayList<>();
availableLanguages.clear();
for (Show show : entityListLanguages) {
MovieLanguage movieLanguage = new MovieLanguage();
movieLanguage.setId(show.getSpokenLanguage());
movieLanguage.setName(show.getSpokenLanguageFormatted());
if (!movieLanguageList.contains(movieLanguage)) {
movieLanguage.setMovieCount(1);
movieLanguageList.add(movieLanguage);
}
}
availableLanguages.addAll(movieLanguageList);
CinemanApplication.getCurrentAppInstance().setAvailableLanguages(availableLanguages);
}
getShowList()在“ movieTheatreShowtimesListItemRecyclerViewAdapter”类中,如下所示:
List<Show> getShowList() {
return showList;
}
答案 0 :(得分:1)
问题最像是将新内容添加到列表中。公用for(Type obj : list)
循环使用Iterator
接口提供的公用Iterable
。但是,在迭代过程中修改列表会抛出ConcurrentModificationException
。
错误代码(引发ConcurrentModificationException):
List<Integer> li = new Random().ints(10000,0,10).boxed().collect( Collectors.toList() );
for(Integer i : li)
{
if(i.intValue() == 5)
{
li.add( Integer.valueOf( 2 ) );
}
}
为防止这种情况,您可以使用ListIterator
界面强制执行的List
。
工作代码:
List<Integer> li = new Random().ints(10000,0,10).boxed().collect( Collectors.toList() );
for(ListIterator<Integer> it = li.listIterator();it.hasNext();)
{
if(it.next().intValue() == 5)
{
it.add( Integer.valueOf( 2 ) );
}
}
注意:这只是使用整数的示例,因为我无法访问OPs类型的对象。
答案 1 :(得分:0)
要在多线程环境中避免ConcurrentModificationException:
您可以将列表转换为数组,然后在数组上进行迭代。这种方法适用于中小型列表,但是如果列表很大,则会对性能产生很大影响。
您可以通过将列表放在同步块中来在锁定时锁定列表。不建议使用这种方法,因为它将停止多线程的好处。
如果使用的是JDK1.5或更高版本,则可以使用ConcurrentHashMap和CopyOnWriteArrayList类。这是推荐的方法。
要避免在单线程环境中发生ConcurrentModificationException:
您可以使用迭代器remove()函数从基础集合对象中删除该对象。但是在这种情况下,您可以从列表中删除同一对象,而不能删除任何其他对象。