Apache POI迭代插入指定段落触发ConcurrentModificationException求助
解决Apache POI迭代段落时插入新段落触发ConcurrentModificationException的问题
你遇到的ConcurrentModificationException,本质是因为for-each循环底层依赖的迭代器有fail-fast机制——当你遍历elements列表时,调用insertNewParagraph会将新段落加入到文档的body元素列表(也就是你正在遍历的elements),导致列表结构被修改,迭代器检测到这个变化后就会抛出异常,哪怕你没显式使用迭代器。
以下是两种可行的解决方案:
方案一:从后往前遍历列表
用普通for循环从列表末尾开始向前遍历,这样插入新段落时,新元素会被添加到当前元素的前方,不会影响后续要遍历的元素索引(因为已经处理过后面的元素),从而避开fail-fast检测。
代码示例:
public void resolveBodyElements1(List<IBodyElement> elements) { // 从后往前遍历,避免插入操作干扰遍历索引 for (int i = elements.size() - 1; i >= 0; i--) { IBodyElement element = elements.get(i); if (PARAGRAPH.equalsIgnoreCase(element.getElementType().name())) { XWPFParagraph paragraph = (XWPFParagraph) element; if (paragraph.getText().equalsIgnoreCase("[{multiline-bulletpoints-markdown}]")) { XmlCursor paragraphCursor = paragraph.getCTP().newCursor(); XWPFParagraph paragraph1 = paragraph.getDocument().insertNewParagraph(paragraphCursor); paragraph1.createRun().setText("This is a test paragraph inserted."); } System.out.println(paragraph.getText()); } } }
方案二:遍历原列表的副本
先将原列表复制为一个独立的副本,遍历这个副本进行判断操作。因为副本和原列表相互独立,修改原列表(插入新段落)不会影响副本的迭代过程,迭代器只会检测副本的结构变化,而副本未被修改,因此不会抛出异常。
代码示例:
public void resolveBodyElements1(List<IBodyElement> elements) { // 遍历原列表的副本,隔离遍历与修改操作 for (IBodyElement element : new ArrayList<>(elements)) { if (PARAGRAPH.equalsIgnoreCase(element.getElementType().name())) { XWPFParagraph paragraph = (XWPFParagraph) element; if (paragraph.getText().equalsIgnoreCase("[{multiline-bulletpoints-markdown}]")) { XmlCursor paragraphCursor = paragraph.getCTP().newCursor(); XWPFParagraph paragraph1 = paragraph.getDocument().insertNewParagraph(paragraphCursor); paragraph1.createRun().setText("This is a test paragraph inserted."); } System.out.println(paragraph.getText()); } } }
内容的提问来源于stack exchange,提问作者Furqan Ahmed
相关产品推荐
相关产品推荐

