比较列表时迭代非法状态

时间:2019-05-11 10:09:48

标签: java arraylist iterator

我正在尝试通过使用迭代器在arraylist中获得类似的项目。 我一直遇到这个错误:

Exception in thread "main" java.lang.IllegalStateException
at java.util.ArrayList$Itr.remove(ArrayList.java:872)
at com.fryslan.updater.wrappers.MethodDataItem.getIntListSimilarities(MethodDataItem.java:97)
at com.fryslan.updater.wrappers.MethodDataItem.matchAbstractNodes(MethodDataItem.java:67)
at com.fryslan.updater.wrappers.MethodDataItem.equals(MethodDataItem.java:182)
at com.fryslan.updater.Updater.<init>(Updater.java:57)
at com.fryslan.updater.Updater.main(Updater.java:99)

我正在使用的代码是这样:

 private ArrayList<Integer> getIntListSimilarities(ArrayList<Integer> base, ArrayList<Integer> target) {

    ArrayList<Integer> matching = new ArrayList<>();
    Iterator baseIterator = base.listIterator();
    Iterator targetIterator = target.listIterator();

    while (baseIterator.hasNext()) {
        while (targetIterator.hasNext()) {

            int bv = (int) baseIterator.next();
            int tv = (int) targetIterator.next();

            if (bv == tv) {
                matching.add(bv);
                baseIterator.remove();
                targetIterator.remove();
                baseIterator = base.listIterator();
                targetIterator = target.listIterator();
            }
        }
    }

    return matching;
}

3 个答案:

答案 0 :(得分:3)

您的代码有很多问题。例如,如果输入是[1]和[1,2],它将抛出NoSuchElementException

baseIterator.remove(); // remove the element from ArrayList<Integer> base
...
baseIterator = base.listIterator(); // new Iterator from the base that had its element removed
...
while (targetIterator.hasNext()); // looking at the 2nd Integer in [1,2]
...
int bv = (int) baseIterator.next(); // NoSuchElementException

此外,如果base的元素多于target,则您的代码可能会陷入无限循环(查找时,第一个循环始终为true,第二个循环始终为false base的最后一个元素)。

在这里,IllegalStateException可能是因为您要在空白的remove上调用ArrayList,但是我无法重现此问题。


如果无法通过此提示修复代码,我将添加解决方案。

提示:将两个循环合并为一个,同时在一个hasNext循环中同时评估2个条件while

答案 1 :(得分:0)

这完成了工作。

 private ArrayList<Integer> getIntListSimilarities(ArrayList<Integer> base, ArrayList<Integer> target) {

    ArrayList<Integer> matching = new ArrayList<>();
    Iterator baseIterator = base.listIterator();
    Iterator targetIterator = target.listIterator();

    while (baseIterator.hasNext() && targetIterator.hasNext()) {

        int bv = (int) baseIterator.next();
        int tv = (int) targetIterator.next();

        if (bv == tv) {
            matching.add(bv);
            baseIterator.remove();
            targetIterator.remove();
        }
    }

    return matching;
}

答案 2 :(得分:0)

无需使用迭代器即可获得两个List<Integer>的公共元素。可能会引发IllegalStateException,因为您正在使用行在迭代时重置迭代器

baseIterator = base.listIterator();
targetIterator = target.listIterator();

我觉得这样做没有任何意义。

这是一个如何查找两个列表的共同元素的示例,它需要Java 8

public static List<Integer> getCommonElementsOf(List<Integer> firstList, List<Integer> secondList) {
    List<Integer> commonElements = new ArrayList<Integer>();

    firstList.forEach(element -> {
        if (secondList.contains(element)) {
            commonElements.add(element);
        }
    });

    return commonElements;
}

这也可以使用经典循环来完成。