【问题标题】:Reverse iteration through ArrayList gives IndexOutOfBoundsException通过 ArrayList 的反向迭代给出 IndexOutOfBoundsException
【发布时间】:2010-10-09 11:29:40
【问题描述】:

当我对 ArrayList 进行反向迭代时,我得到了 IndexOutOfBoundsException。我尝试进行前向迭代,没有问题。我期望并且知道列表中有五个元素。代码如下:

Collection rtns = absRtnMap.values();
List list = new ArrayList(rtns);
Collections.sort(list);

for(int j=list.size();j>0;j=j-1){
  System.out.println(list.get(j));
}

前向迭代 - 工作正常,但对我没用:

for(int j=0;j<list.size();j++){
    System.out.println(list.isEmpty());
    System.out.println(list.get(j));
} // this worked fine

错误:

Exception in thread "Timer-0" java.lang.IndexOutOfBoundsException: Index: 3, Size: 3
    at java.util.ArrayList.RangeCheck(Unknown Source)
    at java.util.ArrayList.get(Unknown Source)
    at model.Return.getReturnMap(Return.java:61)
    at controller.Poller$1.run(Poller.java:29)
    at java.util.TimerThread.mainLoop(Unknown Source)
    at java.util.TimerThread.run(Unknown Source)

另外,如果有人知道反向迭代的更好习惯用法,我很乐意尝试一下。

【问题讨论】:

  • 似乎前向迭代代码没有显示出来——就像这样:for(int j=0;j

标签: java arraylist iteration reverse


【解决方案1】:

list.size() - 1 开始迭代,因为数组(或ArrayList)元素的编号从0 到1 小于列表的大小。这是一个相当标准的成语:

for (int j = list.size() - 1; j >= 0; j--) {
    // whatever
}

请注意,您的前向迭代是有效的,因为它会在之前到达list.size()

【讨论】:

  • 是的,谢谢大家,刚刚回来说这是一个多么愚蠢的问题。并且已经有了几个答案。谢谢。
【解决方案2】:

Java 数组是零索引的。 您必须设置 j = list.size() - 1 并继续直到 j = 0。

【讨论】:

    【解决方案3】:

    list.size() 超过了最后一个允许的索引。

    for(int j = list.size() - 1; j >= 0; j--) {
      System.out.println(list.get(j));
    }
    

    【讨论】:

    • 实际上不,list.size() 不是一个允许的索引——它超出了这个索引——这就是为什么你在你的例子中使用 size() -1 :)
    • 很高兴我在发布自己的解决方案之前在这里阅读了所有解决方案,因为基本上就是这样!
    【解决方案4】:

    完全避免索引?怎么样:

    for (ListIterator iterator = list.listIterator(list.size()); iterator.hasPrevious();) {
      final Object listElement = iterator.previous();
    }
    

    【讨论】:

    • 嗯,它比索引版本更详细。
    • @Seun - 那是因为它使用更多的词来更清楚地解释。我实际上会将其分解为ListIterator iterator = list.listIterator(list.size()); while (iterator.hasPrevious()){ ...iterator.previous(); },因为您没有在for 语句中使用增量器。
    • +1,这具有与 LinkedList 高效工作的额外好处,它使用自己的链接 ListIterator 而不是索引访问,这对于 LinkedLists 来说很慢。
    • @PeterAjtai 是的,这基本上是stackoverflow.com/questions/2102499/…的答案
    【解决方案5】:

    我知道这是一个老问题,但 Java 包含一个 Collections.reverse( List&lt;T&gt; ) 方法。为什么不直接反转它并进行前向迭代?

    【讨论】:

    • 这是迄今为止最好的答案,从问题的标题来看:“反向迭代”,只有在这里才提到这一点。我是通过 Google 到达的,这是唯一对我有用的答案。
    • 这有多复杂?它是复制整个列表,还是只返回一个反向指针?
    • 添加到@Snailer 已经提到的内容 - 对于非常大的列表也会非常慢。通过索引或迭代器进行反转会更好......特别是如果您再次需要原始列表。
    • 确实如此。这当然不是最注重性能的方法。但是对于大多数应用程序,我更喜欢可读性更高的代码,而不是不明显的性能损失。如果您要对大型列表执行多次迭代,请不要使用它!
    • 小心使用这个答案。反转列表然后对其进行迭代与反向迭代列表非常不同。前者使列表处于与您开始时不同的状态,后者不会。
    【解决方案6】:

    最优雅的方法是反转数组,然后使用直接(甚至隐式)迭代器:

    Collections.reverse(arrayList);
    for (Object item : arrayList) {
        ...
    }
    

    【讨论】:

    • 如上面对这个问题的另一个答案 (stackoverflow.com/a/6575124/877472) 所述,Collections.reverse 方法反转传入的集合,这意味着如果您想在其原始方向,这对于非常大的收藏可能会很昂贵。
    【解决方案7】:

    如果列表相当小以至于性能不是真正的问题,可以使用Google GuavaLists-class 的reverse-metod。产生漂亮的for-each-code,原始列表保持不变。此外,反向列表由原始列表支持,因此对原始列表的任何更改都将反映在反向列表中。

    import com.google.common.collect.Lists;
    
    [...]
    
    final List<String> myList = Lists.newArrayList("one", "two", "three");
    final List<String> myReverseList = Lists.reverse(myList);
    
    System.out.println(myList);
    System.out.println(myReverseList);
    
    myList.add("four");
    
    System.out.println(myList);
    System.out.println(myReverseList);
    

    产生以下结果:

    [one, two, three]
    [three, two, one]
    [one, two, three, four]
    [four, three, two, one]
    

    也就是说myList的反向迭代可以写成:

    for (final String someString : Lists.reverse(myList) {
        //do something
    }
    

    【讨论】:

      【解决方案8】:

      你可以反转一行

      Collections.reverse(list);

      ArrayList arrayList = new ArrayList();
      
      arrayList.add("A");
      arrayList.add("B");
      
      System.out.println("Before Reverse Order : " + arrayList);
      
      Collections.reverse(arrayList);
      
      System.out.println("After Reverse : " + arrayList);
      

      输出

      Before Reverse Order : [A, B]
      After Reverse : [B, A]
      

      【讨论】:

        【解决方案9】:

        如果您对 foreach 循环感到满意,您可以这样做。

        List<String> list = new ArrayList<String>();
        list.add("ABC");
        list.add("DEF");
        list.add("GHI");
        
        ListIterator<String> listIterator = list.listIterator(list.size());
        
        while(listIterator.hasPrevious()){
          System.out.println(listIterator.previous());
        }
        

        【讨论】:

          猜你喜欢
          • 2012-11-06
          • 2017-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-22
          • 2013-06-22
          • 2011-01-13
          相关资源
          最近更新 更多