【问题标题】:List size has unexpected value列表大小具有意外值
【发布时间】:2016-06-21 16:54:04
【问题描述】:

假设循环中出现以下情况:

LinkedList<String> myList = someMethodReturnsList();
int start = 0, end = 0;

while (end < myList.size() && someOtherCondition)
    ++end;

List<String> subList = myList.sublist(start, end);

... (do stuff and possibly alter list)

start = end;

我遇到的情况是仅在某些时候,对sublist 的调用会抛出IndexOutOfBoundsException。鉴于我对end &lt; myList.size() 的第一次测试,这让我很困扰,所以我编写了一些调试代码。我的调试代码告诉我,在while 循环和调用sublist 之间,我的end 值最终为34,而myList.size() 返回33。

这怎么可能?在我的程序中没有其他线程可以在这个列表上运行,那么我的循环检查是如何通过并将end 增加到 34 的?

编辑:这始终发生在我的代码执行的特定点,所以这不是一个侥幸错误,但它不会发生在这个函数的每个输入中,这让这更加奇怪。

【问题讨论】:

  • 唯一合乎逻辑的解释是 someOtherCondition 正在修改 List,或者 someMethodReturnsList 保留对 List 的引用并正在修改它。
  • 这两个听起来合乎逻辑。然而,someMethodReturnsList 总是创建一个new 实例,而someOtherCondition 只是从myListendth 元素中检查一个属性(只读)。
  • 有趣。可以同时包含这两个吗?而且,顺便说一句,LinkedList 绝对不是做myList.get(end)myList.subList 的好课。
  • 您确定 end 的值是 34 而不是 33?不要听起来居高临下之类的。只是说如果它是 33,它仍然会抛出 IndexOutOfBoundsException :)
  • @JalithaDeSilva 根据List 的文档,如果end 为33,则不应抛出它。 List.sublist 的第二个参数是 exclusive 最后索引。也就是说,end 应该能够获得 34 的值是没有任何意义的。

标签: java list indexoutofboundsexception


【解决方案1】:

你所描述的是不可能的。

实际上,实现这一点的唯一方法是您自己进行调试:代码元素检查等 IDE 功能可以在应用程序在断点处暂停时执行部分代码。

您必须使用调试器工具更改end 的值。

【讨论】:

  • 在这种情况下我没有使用我的调试器。我知道我所描述的情况应该是不可能的。唯一有意义的方法是 myList.size() 在循环期间是否为 34 并且在它之后以某种方式递减。这就是我来这里的原因;我完全不明白这怎么会发生。
【解决方案2】:

我的猜测与@Jalitha 所说的一致,相差一个:子列表调用应该是:

List<String> subList=myList.sublist(start,end-1);

您有时得到正确数字的原因可能与您的 someOtherCondition 有关。

记住 size() 比最后一个索引大 1 并且 subList 对索引起作用。

我会将此放在评论中,但由于声誉问题而无法发表:(

【讨论】:

  • 感谢您的接机!没意识到,我现在觉得有点傻:P 我也会编辑我的答案。
  • Lol np,但它似乎不适用于 2mac 或者不够清晰?
  • 无视,我只是看到其他的cmets并自己尝试了一下,使用大小应该可以正常工作。我认为我们可能需要查看更多实际代码才能弄清楚这一点?
【解决方案3】:

啊哈!经过仔细调试,我已经弄清楚了。

事实证明,在发生此异常的循环迭代中,end 的值从 34 开始。因此,增量循环通过,并且存在索引错误。

原因是在上一次迭代中,myList.size() 为 36,但在该循环过程中,删除了 3 个元素。

【讨论】:

    【解决方案4】:

    在我看来,这是一个经典的“一对一”数组错误。您很可能拥有end 等于myList.size(),然后比您的本意多引用一个。 从您的 while 循环中,例如如果数组有 5 个元素:

    while (end < 5 && conditions)
    {
       ++end; //results in end being 5
    }
    

    以后就这样了

    List<String> subList = myList.sublist(0, 5);
    

    并且 5 超出范围,因为数组只有索引 0,1,2,3,4

    我认为你应该选择while (end+1 &lt; 5 &amp;&amp; conditions)myList.sublist(0, end-1);

    编辑:感谢@Justen,指出我的错误。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-06
      • 1970-01-01
      • 1970-01-01
      • 2016-03-08
      • 1970-01-01
      相关资源
      最近更新 更多