【问题标题】:Get the current index of a for each loop iterating an ArrayList为每个循环迭代 ArrayList 获取 a 的当前索引
【发布时间】:2014-01-24 13:04:15
【问题描述】:

我正在使用 for each 循环迭代 ArrayList,但我不知道如何获取循环所在的当前索引。

我用谷歌搜索过,但找不到任何有用的东西。

如果有人能告诉我如何获取当前索引,我将不胜感激。

【问题讨论】:

    标签: java arraylist foreach indexing


    【解决方案1】:

    只需使用传统的 for 循环:

    for (int i = 0; i < yourArrayList.size(); i ++) {
        // i is the index
        // yourArrayList.get(i) is the element
    }
    

    【讨论】:

    • 有时旧方法是最好的方法,尤其是因为传统的 for 循环具有明确定义的行为。如果你能回答这个问题,加分,为什么传统的 for 循环变量是 i,j,k?
    • “i”是算法中“index”这个词的总和,字母表后面是“j”和“k”。
    【解决方案2】:

    窃取门把手的答案,但做出改变,否则会让我像海盗一样发疯:

    int arraySize = yourArrayList.size();
    for (int i = 0; i < arraySize; i ++) {
        // i is the index
        // yourArrayList.get(i) is the element
    }
    

    或者

    int currentPosition = 0;
    for (myItemType myItem :myArrayList) {
        // do stuff
    
        currentPosition++;
    }
    

    【讨论】:

    • 为什么这会让你发疯?你的改变会让我发疯!
    • 为什么每次循环都调用size函数?调用一次,得到答案,然后使用答案。这是您尝试做的事情的意图,没有所有额外的函数调用。
    • 如果您正在为 Android 编写代码,文档强烈建议您使用 @Zak 的方式来精确地避免重复的函数调用。如果更改循环内列表的大小,可以arraySize=yourArrayList.size() 或根据需要使用++--
    • @assylias - 跨编程语言、编译器和平台,尚不清楚哪些编译器/VM 可以优化来自 for 循环内部的重复函数调用。此外,代码的编写方式并未显示出不重复进行该函数调用的意图。这就是为什么它让我发疯的原因,以及为什么我将函数调用单独放在一行上,这样我就可以在语义上告诉我的意图,而无需编译器进行优化猜测。
    • 我认为这个问题要微妙得多。如果列表在循环期间永远不会改变大小,则无需重复调用 size 方法。如果 VM 也可以优化对 size 的重复调用,我会感到惊讶,因为它必须证明在循环期间不会对列表进行任何修改(可能是引用计数?)。我前段时间对此进行了测试,重复的调用并没有被优化掉,也许是现在。我使用for( int i =0, n = list.size(); i&lt;n; i++ ) 表示善意。
    【解决方案3】:

    如果它在容器中,您可以使用list.indexOf(objectYouWantToFind); 获取其索引,否则您将收到-1

    【讨论】:

    • 这正是上述问题的准确答案,我不明白为什么它没有得到最多投票
    • @robel indexOf 的一个问题是性能问题。 indexOf 每次调用它时都会对所有元素进行线性扫描,而 @Doorknob 使用显式 for 循环的回答避免了额外的扫描。例如,如果您正在遍历一个循环并每次调用 indexOf,那么您有 O(n^2)。如果您将get 视为 O(1),门把手的答案是 O(n)。您可能会对此链接感兴趣:java-performance.info/arraylist-performance
    • @robel 如果对象不是唯一的,它也不起作用。
    【解决方案4】:

    使用传统循环。 Java 中的 For-each 语句不承诺对集合进行排序。真正知道索引的唯一方法是在每次迭代时查询列表。

    for(int i=0; i<list.size; i++){
        // you have your index, i
        // the item is at list.get(i)
    }
    

    依靠 iterator() 实现,您还可以使用替代方案(在 cmets 中 +1 Zak):

    int position = 0;
    for(Item i : list){
    
        // do stuff with `i`
    
        // increase position as the last action in the loop
        position++;
    }
    

    来自文档:Iterator&lt;E&gt; iterator() Returns an iterator over the elements in this list in proper sequence

    这就是为什么我通常不使用for的简写形式:

    import java.util.ArrayList;
    import java.util.Iterator;
    
    
    public class MyList<T> extends ArrayList<T> {
        // the main function to run the example
        public static void main(String[] args){
            // make a list of my special type
            MyList<Integer> list = new MyList<Integer>();
    
            // add 10 items to it
            for (int i =0; i<10; i++){
                list.add(i);
            }
    
            // print the list using the for-each mechanism (it's actually an iterator...)
            for (Integer i : list){
                System.out.println(i);
            }
        }
    
        // I like lists that start at 3!
        // make my list return an iterator in the middle of the list...
        @Override
        public Iterator<T> iterator(){
            return this.listIterator(3);
    
        }
    
    }
    

    显然,您希望在第一次迭代中拥有第一项,但显然情况并非如此,因为迭代器可以通过多种方式实现,而 Java 的 foreach 取决于底层的 iterator 实现。

    另外,您必须在循环结束时使用position++,这可能容易出错(不知道,通常不使用它..)。

    也就是说,它确实提高了可读性,就像这个 stackoverflow question 关于 Java 的 foreach 中提到的那样。

    如需了解更多信息,请参阅How does the Java for each loop work?

    【讨论】:

    • 这是不正确的:来自文档:Iterator iterator() 以正确的顺序返回此列表中元素的迭代器。上面给出的示例将是规范的错误覆盖实现。问题不在于使用迭代器,而在于实现 iterator() 的定义时出现错误。
    • @Zak 谢谢,有什么理由不使用 for-each 的“currentPosition”解决方案吗?
    【解决方案5】:

    如果是迭代一个List,可以使用indexOf()方法,例子:

    List<Animal> animals = new ArrayList<Animal>();
    Animal a = new Animal();
    a.setAnimalCode(1);
    animals.add(a);
    
    a = new Animal();
    a.setAnimalCode(35);
    animals.add(a);
    
    a = new Animal();
    a.setAnimalCode(12);
    animals.add(a);
    
    for(Animal a: animals)
       if(animal.getAnimalCode()==35)
          System.out.println("Index of chosen one: "+animals.indexOf(a));
    

    选择的索引:2

    【讨论】:

      【解决方案6】:

      有点骇人听闻,但你肯定可以在 for each 循环中有一个索引:

      public class Counter{
        private Integer i;
        public Counter(Integer i) { this.i = i; }
        public void incrementOne(){ this.i = getI() + 1; }
        //getter and setter for i
      }
      

      而且,在你的 for each 循环中的其他地方:

      外星人.java

      Counter counter = new Counter(0);
      List<String> list = new ArrayList<>();
      //have some values in the list
      list.forEach(i-> {
        //i will have the value and the counter will have the count!
        System.out.println(counter.getI());
        counter.incrementOne();
      });
      

      否则,您总是有一个 list.indexOf(i),其中 i 是列表中的每个对象。 :P

      【讨论】:

        猜你喜欢
        • 2011-03-20
        • 2020-08-12
        • 2017-01-24
        • 2014-09-12
        • 2012-06-21
        • 1970-01-01
        • 2020-08-07
        • 2015-09-15
        • 1970-01-01
        相关资源
        最近更新 更多