使用Iterator时如何获取当前循环索引?


107

我正在使用Iterator来遍历一个集合,我想获取当前元素的索引。

我怎样才能做到这一点?



1
@finnw我不认为它们是重复的。这个问题是使用Iterator提出的,另一个是使用for-each循环。这两个问题都可以通过类似的方法解决,因此答案不是问题,而是重复的。
罗伯特·

Answers:


92

使用您自己的变量并在循环中将其递增。


6
但也请参阅@ mateusz-dymczyk关于的建议it.nextIndex()。当集合是列表时很有用。
noamtm'9

113

我有同样的问题,发现使用ListIterator可以工作。与上面的测试类似:

List<String> list = Arrays.asList("zero", "one", "two");

ListIterator iter = list.listIterator();

while (iter.hasNext()) {
    System.out.println("index: " + iter.nextIndex() + " value: " + iter.next());
}

确保在实际获得next()之前调用nextIndex。


5
感谢您提及“确保在实际获得next()之前先调用nextIndex”
Gangadhar JANNU

谢谢,我以前不知道这一点。我要警告的是ListIterator是双向的,而Iterator是单向的。只要您避免与有效的游标来回移动,那么您应该是安全的。
user2910265

28

这是使用您自己的变量并保持简洁的一种方法:

List<String> list = Arrays.asList("zero", "one", "two");

int i = 0;
for (Iterator<String> it = list.iterator(); it.hasNext(); i++) {
    String s = it.next();
    System.out.println(i + ": " + s);
}

输出(您猜对了):

0: zero
1: one
2: two

优点是您不必在循环内增加索引(尽管您需要注意每个循环仅调用Iterator#next一次-只需在顶部执行即可)。


3
如果您自己创建迭代器,则也可以使用ListIterator,并且不需要单独的int变量。
罗伯特·克莱姆

1
如果您对Arrays.asList使用“静态导入”,则只需编写asList("zero", "one", "two")
karmakaze

这正是我在阅读Paul的答案之前所做的方式。我强烈不建议您这样做,因为我看不到任何好处。您是否认为有优势(提到的优势除外)。为什么不使用for-each循环?如果您使用自己的变量,则无需显式定义Iterator。
威利·曼策尔

@progressive_overload,即使您需要一个迭代器(根据每个问题,例如传递给库),该示例也不会显示。在此示例中,您在循环外有一个变量,需要小心地调用#next一次。在Paul的示例中,循环之外没有任何变量,但是您需要小心地将#next和#nextIndex一起调用一次(实际上,如果多次使用,它们将被拉入局部变量,而该示例不会这样做) t显示)。
汤姆·克利夫特

23

您可以使用ListIterator进行计数:

final List<String> list = Arrays.asList("zero", "one", "two", "three");

for (final ListIterator<String> it = list.listIterator(); it.hasNext();) {
    final String s = it.next();
    System.out.println(it.previousIndex() + ": " + s);
}


4

使用ListIterator遍历Collection。如果Collection不是以List开头的列表Arrays.asList(Collection.toArray()),请先将其转换为List。


3

只是做这样的事情:

        ListIterator<String> it = list1.listIterator();
        int index = -1;
        while (it.hasNext()) {
            index++;
            String value = it.next();
            //At this point the index can be checked for the current element.

        }

4
调用indexOf()将需要对设备列表进行其他扫描。简单地增加本地计数器会更快。
格雷格·布朗

1
同意 这不是最有效的解决方案。
晴,

1
看起来您更新了示例以提高效率。
格雷格·布朗


1

这里

iterator.nextIndex()将提供元素索引,随后调用会返回该元素的索引next()


接口Iterator具有NOT nextIndex()方法。您需要为此明确使用ListIterator,但是OP专门询问了Iterator。
弗朗·马佐亚

0

您只需使用iterator.nextIndex()即可返回迭代器所在的当前索引。这可能比使用您自己的计数器变量(仍然可以使用)容易一些。

public static void main(String[] args) {    
    String[] str1 = {"list item 1", "list item 2", "list item 3", "list item 4"};
    List<String> list1 = new ArrayList<String>(Arrays.asList(str1));

    ListIterator<String> it = list1.listIterator();

    int x = 0;

    //The iterator.nextIndex() will return the index for you.
    while(it.hasNext()){
        int i = it.nextIndex();
        System.out.println(it.next() + " is at index" + i); 
    }
}

此代码将一次遍历list1列表中的一项,并打印该项的文本,然后“在索引处”,然后将打印迭代器在其处找到的索引。:)


1
实际上,您的代码是一对一的,因为它尝试在调用it.next()之后显示索引。
Henrik AastedSørensen2014年

0

尽管您已经有了答案,但请考虑添加一些信息。

正如您明确提到集合的那样,您不能使用它listIterator来获取所有类型的集合的索引。

列表接口 -ArrayList,LinkedList,Vector和Stack。

既有iterator()listIterator()

设置接口 -HashSet,LinkedHashSet,TreeSet和EnumSet。

只有 iterator()

地图接口 -HashMap,LinkedHashMap,TreeMap和IdentityHashMap

没有迭代器,但可以使用通过keySet()/ values()entrySet()as 进行迭代,keySet()entrySet()返回Setvalues()return Collection

因此,最好将其iterators()与值的连续递增结合使用以获取任何集合类型的当前索引。


-1

这将是最简单的解决方案!

std::vector<double> v (5);

for(auto itr = v.begin();itr != v.end();++itr){

 auto current_loop_index = itr - v.begin();

  std::cout << current_loop_index << std::endl;

}

在带有-std=c++11标志的gcc-9上测试

输出:

0
1
2
3
4

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.