【问题标题】:moving iterator statement makes code compile移动迭代器语句使代码编译
【发布时间】:2018-10-17 02:39:43
【问题描述】:

我创建了一个基本上只是测试近似值的代码。 ArrayLists 的运行时。但是,如果一行代码被移动点,代码将无法编译。这是编译的代码。

public class ArrayTest {

    public static void main(String []args) {
        ArrayListTest();
    }

    private static void ArrayListTest() {
        //initializes random variable, accumulator and iterator and ArrayList
        Random rand = new Random();
        Float accum = 0F;
        ArrayList<Float> al = new ArrayList<>();

        //finds time of program pre-running
        long startTime = System.currentTimeMillis();

        //Populates ArrayList
        for (int i = 0; i < 20000000; i++) al.add(rand.nextFloat());

        //finds time of program post-running
        long endTime = System.currentTimeMillis();

        //Iterates through ArrayList, summing elements
        Iterator<Float> itr = al.iterator();
        while(itr.hasNext()) {
            accum += itr.next();
        }

        //Finds time of summing ArrayList
        long sumEndTime = System.currentTimeMillis() - endTime;

        //Prints meaningful conclusion
        System.out.print("ArrayList takes: " + (endTime - startTime) / 1000.0 + " seconds to initialize.\n");
        System.out.print("ArrayList takes: " + (sumEndTime / 1000.0) + " second to sum. \n");
    }
}

但是,如果移动“Iterator itr = al.iterator();”在数组列表声明之后,它不会编译。这是为什么呢?

【问题讨论】:

  • "到代码的开头..." -- 代码的开头在哪里到底是什么?
  • 显然Iterator itr = al.iterator(); 行必须放在之后 ArrayList&lt;Float&gt; al = new ArrayList&lt;&gt;();,在您创建了数组列表之后。这只是常识,不是吗?否则没有意义。
  • 你不能创建迭代器 before 你已经向 ArrayList 添加了一些东西(不使用迭代器本身),否则它会失效,虽然这不会导致编译错误。
  • ???你的代码应该仍然编译——你确定这是发生的,编译器不允许你创建一个类文件吗?在我看来,它可以正常编译并运行,但运行时会引发异常。
  • 我会说 90% 的问题 cmet 是要求清晰的问题,如果我们似乎在吹毛求疵,很抱歉,但编程语言编译器是死板和无情的,因此程序员也必须学会这样做.好吧,也许不是“无情”,只是有点强迫症,是的。

标签: java compilation iterator


【解决方案1】:

如果您将迭代器的创建移到 ArrayList 创建之后,您的代码编译得很好,并且代码将运行,但它会抛出 ConcurrentModificationException,因为您正在更改列表 创建迭代器并这样做不使用迭代器。这将使迭代器处于无效状态。

如果你在这里创建迭代器:

ArrayList<Float> al = new ArrayList<>();
Iterator<Float> itr = al.iterator();

然后在此处添加到ArrayList:

// Populates ArrayList
for (int i = 0; i < 20000000; i++)
    al.add(rand.nextFloat());

迭代器现在正在尝试遍历自创建以来已更改的集合,这将导致在此处抛出 ConcurrentModificationException:

while (itr.hasNext()) {
    accum += itr.next();
}   

要解决此问题,请仅在创建迭代器后使用迭代器 修改集合。这主要是在从集合中删除项时完成的。如果您需要添加项目,则需要使用 ListIterator,而不是普通的 Iterator,或者在填充集合之后创建您的迭代器。

例如,

ArrayList<Float> al = new ArrayList<>();
// Iterator<Float> itr = al.iterator();       
ListIterator<Float> listItr = al.listIterator();

long startTime = System.currentTimeMillis();

for (int i = 0; i < 20000000; i++) {
    // al.add(rand.nextFloat());
    listItr.add(rand.nextFloat());  // add with the ListIterator
}

long endTime = System.currentTimeMillis();

while (listItr.hasNext()) {
    accum += listItr.next();
}

您还想阅读:What is the difference between run-time error and compiler error?
因为这种区别非常重要,尤其是在本网站上询问时。它们是两个非常不同的广泛错误类别,并且在大多数情况下,它们不重叠。

【讨论】:

    猜你喜欢
    • 2023-03-13
    • 2010-10-05
    • 1970-01-01
    • 2022-11-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多