如何将一个迭代器复制到另一个迭代器?

2022-09-02 00:16:15

我需要迭代 for 循环的每次迭代的值集,但只有对于第一次迭代,它才能正常工作。此后返回 。itr.hasNext()false

Iterator<String> itr = getQuestionIterator(File file);

for(Person p : persons)
{
    while(itr.hasNext())
    {
        String question = itr.next();
        ........
        ........
    }
}

这种行为对我来说很清楚。

一种解决方案可能是在 for 循环中调用方法,因此对于每个 for 循环迭代,它都会被重新初始化。但这是非常低效的方法,因为它是独立的。getQuestionIterator(File file)itr

我试过了这个,但它也不起作用,因为它只包含参考。Iterator<String> temp = itr

有没有办法将迭代器复制到另一个迭代器或任何其他更好的方法中?


答案 1

An 是按顺序处理数据的最小可能的 API,因此它从基础数据源中抽象出来。由于它只能向前移动()而没有任何重置或倒带的选项,因此它是一个单向对象,必须在使用后丢弃。由于它提供的API有限,因此不可能在不知道实现和/或基础数据源的情况下简单地“复制”它。Iteratornext()

因此,有四种方法可以处理您的问题:

(1) 从基础数据源重新获取新的迭代器

每次需要(再次)迭代数据时,只需调用即可。getQuestionIterator(File file)

  • 优点:易于使用,易于实施。无需缓存。
  • 缺点:性能(例如,文件必须再次读取/解析)。在此期间,基础数据源可能已更改。

(2) 将所有处理代码合并到一个迭代循环中

而不是。。。

iterator = /* get new iterator */
while (iterator.hasNext()) {
    String question = iterator.next();
    /* first processing step */
}
iterator = /* get new iterator */
while (iterator.hasNext()) {
    String question = iterator.next();
    /* second processing step */
}
iterator = /* get new iterator */
while (iterator.hasNext()) {
    String question = iterator.next();
    /* third processing step */
}
...

...合并所有步骤:

iterator = /* get new iterator */
while (iterator.hasNext()) {
    String question = iterator.next();
    /* first processing step */
    /* second processing step */
    /* third processing step */
    ...
}
  • 优点:只需要一个迭代器。无需缓存。
  • 缺点:并非总是可能的,例如,如果处理步骤具有依赖性。

(3) 将所有元素复制到本地缓存(集合

循环访问所有项一次,并将它们放入可用于获取任意数量的迭代器的本地集合中:

// read everything into a local cache
Collection<String> cache = new ArrayList<>();
while (iterator.hasNext()) cache.add(iterator.next());

// now you can get as many iterators from cache as required:
Iterator<String> iter = cache.iterator();
// use iter

iter = cache.iterator(); // once more
// use iter
...
  • 优点:一旦所有数据都在缓存中,实施简单,速度快。
  • 缺点:需要额外的内存用于缓存。

(4) 修改数据源 API,让其实现处理问题

含义: 更改以返回 一个而不是 .您可以从中获得任意数量的迭代器:getQuestionIterator(File file)Iterable<String>Iterator<String>Iterable

Iterable<String> iterable = getQuestionIterator(File file);
Iterator<String> iter = iterable.iterator();
// use iter

iter = iterable.iterator(); // once more
// use iter
  • 优点:基础数据源最知道如何缓存数据。如果基础数据源已使用缓存,则无需复制数据。
  • 缺点:并不总是能够更改 API。

答案 2

这取决于代码块的确切内容,但为什么不翻转循环呢?让外部循环遍历文件,对于每次迭代,遍历所有 s:Person

Iterator<String> itr = getQuestionIterator(File file);
while(itr.hasNext()) 
{
    String question = itr.next();
    for(Person p : persons)
    {    
        ........
        ........
    }
}