【问题标题】:Iterator retrieve first value and place it back on the same iterator迭代器检索第一个值并将其放回同一个迭代器
【发布时间】:2012-08-17 19:29:13
【问题描述】:

我有以下情况:我有一个现有的迭代器 Iterator<String> it 并且我在它的头上进行迭代(比如前 k 个元素,它们是标记的元素,即它们以 '*' 开头)。知道标记元素结束的唯一方法是注意到第 (k+1) 个元素没有标记。

问题是,如果我这样做,迭代器 it 将不会在下次调用 next() 时为我提供第一个值。

我想将此迭代器传递给一个方法,因为它是唯一的参数,并且我想避免更改它的签名和它的实现。我知道我可以这样做:

   public void methodAcceptingIterator(Iterator<String> it) //current signature

   //change it to 

  public void methodAcceptingIterator(String firstElement, Iterator<String> it)

但这看起来像是一种工作方法/hack,降低了代码的优雅性和通用性,所以我不想这样做。

有什么办法可以解决这个问题吗?

【问题讨论】:

    标签: java collections iterator


    【解决方案1】:

    您可以使用 Guava 的 PeekingIterator(链接包含静态方法的 javadoc,给定 Iterator,将返回包装 PeekingIterator)。这包括一个方法T peek(),它会向您显示下一个元素,而无需前进。

    【讨论】:

    • 有趣的迭代器!不知道!这意味着我可以在迭代器之外使用它并保留相同的签名。问题是我无法控制底层迭代器。它由框架传递给我的应用程序:(
    • 根据这件事的工作原理,这可能是一个解决方案。想法是它的底层迭代了一个巨大的数据集,存储在磁盘上。
    【解决方案2】:

    解决方案是创建您自己的迭代器实现,该实现存储firstElement 并使用现有迭代器作为底层迭代器,将其余元素的请求委托给。

    类似:

      public class IteratorMissingFirst<E> implements Iterator<E>{
    
    private Iterator<E> underlyingIterator;
    private E firstElement;
    private boolean firstElOffered;
    
    public IteratorMissingFirst(E firstElement, Iterator<E> it){
        //initialize all the instance vars
    }
    
    public boolean hasNext(){
        if(!firstElOffered && firstElement != null){
                return true;
        }
        else{
            return underlyingIterator.hasNext();
        }
    }
    
    public E next(){
        if(!firstElOffered){
            firstElOffered = true;
            return firstElement;
        }
        else return underlyingIterator.next();
    }
    
    public void remove(){
    
    }
    }
    

    【讨论】:

      【解决方案3】:

      为什么不让methodAcceptingIterator 将它从迭代器中取出的第一个元素存储在一个变量中?或者 - 在紧要关头 - 只需将 Iterator 的内容复制到方法开头的 ArrayList 中;现在您可以随意重温元素。

      【讨论】:

      • 我不能使用 ArrayList 因为这个迭代器有大量的值。它不适合主内存。
      • 目前还不清楚您想对第一个元素做什么,以及为什么不能将其作为方法的第一步存储在变量中。
      • 我当然可以这样做,但这意味着修改 methodAcceptingIterator 的实现
      • ...是的。是的,它确实。我无法想象任何不涉及修改methodAcceptingIterator 实现的解决方案,包括上面建议的其他解决方案。但它不会改变签名,这与你可能得到的一样好。
      【解决方案4】:

      使用 Guava,您可以使用 Iterables 类中的一些方法以更简单的方式实现 Razvan 的解决方案:

      Iterators.concat(Iterators.singletonIterator(firstElement), it)
      

      这为您提供了一个类似于IteratorMissingFirst 的迭代器,如果您需要查看前面的多个元素(但它会创建两个对象而不是仅一个),它很容易扩展。

      【讨论】:

        猜你喜欢
        • 2019-04-26
        • 2012-10-23
        • 2010-09-23
        • 2018-09-23
        • 1970-01-01
        • 2019-05-11
        • 1970-01-01
        • 2016-07-24
        • 2021-10-05
        相关资源
        最近更新 更多