#java-8 #java-stream #concurrentmodification #jgrapht
Вопрос:
У меня есть набор<Объектов>, который я хочу отфильтровать по классам, чтобы получить набор<Объектов><Foo> (т. Е. Подмножество объектов, которые являются <Foo> instanceof
Foo). Для этого с помощью Java-8 я написал
Set<Foo> filtered = initialSet.parallelStream().filter(x -> (x instanceof Foo)).map(x -> (Foo) x).collect(Collectors.toSet());
Это бросание ConcurrentModificationException
:
java.util.ConcurrentModificationException
at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1388)
at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
Проблема, по-видимому, в коллекционере, но я понятия не имею, почему.
Комментарии:
1. Вы пробовали
initialSet.stream()
вместоinitialSet.parallelStream()
этого ?2. Параллельный поток здесь вам ничего не даст. Параллелизм имеет накладные расходы. Не разбрасывайтесь им просто потому, что это звучит круто. Лучшее эмпирическое правило: никогда не используйте параллельный поток, если вы на самом деле не установили, что существует узкое место, которое решит параллельный поток. Я ежедневно работал с потоками Java в течение последних 5 лет, и мне нужно было использовать параллельные потоки, возможно, один раз.
3. Я пробовал это обоими способами (т. Е. потоком и параллельным потоком) и получил одинаковые результаты. Я также разбил его на отдельные части: Поток<Объект> stage1 = initialSet.stream(); Поток<Объект><Объект> stage2 = stage1.filter(x -<Объект>> (x экземпляр Foo)); но у него были те же результаты.
4. Исключение указывает на то, что исходная коллекция была изменена во время выполнения операции. Поскольку ни одна из показанных вами операций не изменяет исходную коллекцию, проблема должна быть в коде, который вы не показали. Также очень интересно , что вы говорите , что у вас
Set<Objects>
, предположительноinitialSet
, есть, но исключение явно связано с операцией, обрабатывающейArrayList
…5. @Хольгер: ты прав. Код потока и сбора был отвлекающим маневром. Проблема оказалась в том, что происходило в другом месте (см. Мой ответ ниже).
Ответ №1:
Нашел (и исправил) проблему. Проблема initialSet
в том, что . Это достигается путем вызова сторонней библиотеки (в данном случае DirectedPseudoGraph
экземпляра JGraphT). Базовый график был изменен в другом потоке. Поскольку значение initialSet
возвращается по ссылке, результатом является ConcurrentModificationException
.
Поэтому реальная проблема заключается не в потоковой обработке, а в использовании графика, который возвращал набор, который не был потокобезопасным. Решение состояло в том, чтобы использовать AsSynchronizedGraph
.
Комментарии:
1. Исходный вопрос не содержит достаточно подробностей, чтобы кто-либо мог понять этот ответ. Исходный вопрос не содержит кода и в тегах упоминается только jgrapht.