【问题标题】:How to implement a jump iterator如何实现跳转迭代器
【发布时间】:2015-01-27 15:43:02
【问题描述】:

实现跳转迭代器的next()和hasNext(),构造函数与另一个迭代器一起传递。 next() 函数将返回 iterator.next().next()

我已经实现了下面的代码,它看起来一点也不优雅。 而对于列表 {1, 9, 8, 7, 8, 2, 5},它只会输出 9, 7, 2。 有什么更好的方法吗?

基本上这个跳转迭代器是试图迭代每个元素一个距离,例如对于1,2,3,4,5,它会返回1,3,5

public class JumpIterator implements Iterator<Integer> {
    private Iterator<Integer> it;

    public JumpIterator(List<Integer> list){
        it = list.iterator();
    }

    @Override
    public boolean hasNext() {
        if(!it.hasNext()){
            return false;
        }else{
            it.next();
            return it.hasNext();
        }
    }

    @Override
    public Integer next() {
        return it.next();
    }
}

【问题讨论】:

  • 如果JumpIterator 的目的是在每个next() 中“跳过一个并取一个”,那么您的结果现在是 100% 合规的。看来您还希望第一个值不被跳过!

标签: java iterator


【解决方案1】:

在我看来,您的问题出在函数“hasNext”中

为什么要覆盖它?你想获得什么行为?

当 it.hasNext() 返回 true 时,你会消耗一个你不应该消耗的值,因为它在那里使用了 it.next()。

【讨论】:

  • 是的,基本上这个跳转迭代器是试图迭代每个元素一个距离,例如对于1,2,3,4,5,它会返回1,3,5。所以在第一个位置, hastNext() 应该检查它是否在第三个位置有元素。我们如何在 hasNext() 中实现它而不实际调用 next() 以继续到第二个位置?
【解决方案2】:

这些方法实现目前假设程序总是交替调用hasNextnext,从长远来看这可能会带来一些问题。

JumpIterator jit = ...;
jit.hasNext();
jit.haxNext(); // skipped a relevant value
jit.next();
jit.next(); // obtained two adjacent values

这是解决问题的方法。简而言之,我正在跟踪是否已经检查了下一个值,在这种情况下,我已经跳过了一个值。

public class JumpIterator implements Iterator<Integer> {
    private Iterator<Integer> it;
    private boolean skipped;

    public JumpIterator(List<Integer> list){
        it = list.iterator();
        skipped = false; 
        // if you want to take the first value from the stream,
        // change skipped to true
    }

    @Override
    public boolean hasNext() {
        if (it.hasNext() && !skipped) {
            it.next();
            skipped = true;
        }
        return it.hasNext();
    }

    @Override
    public Integer next() {
        if (!skipped) {
            it.next();
        }
        skipped = false;
        return it.next();
    }
}

除此之外,如果预期目标是每次检索元素时“跳过一次并获取下一个”,则跳转迭代器会起作用。在这种逻辑下,在序列[1,2,3,4] 上使用迭代器会得到[2,4]。如果您想改用[1,3](如,不跳过第一个值),只需调整如上所示的实现。

【讨论】:

    【解决方案3】:

    我会把它做成这样的

    public class JumpIterator implements Iterator<Integer> {
      private Iterator<Integer> it;
    
      public JumpIterator(List<Integer> list){
        this.it = list.iterator();
      }
    
      @Override
      public boolean hasNext() {
        //hasNext should be idempotent (should not modify the state)
        return it.hasNext();
      }
    
      @Override
      public Integer next() {
        //If the user didn't check hasNext()
        // NoSuchElementException might be thrown,
        // which is interface-compliant, so we just don't care
        Integer nNext = it.next();
    
        //Now we must skip the next value
        if (it.hasNext()) it.next();
        return nNext;
      }
    }
    

    这将不会跳过第一个元素。 如果你想这样做,那么你需要 E_net4 描述的惰性跳过策略。我只是把它排除在外:

    public class JumpIterator implements Iterator<Integer> {
      private Iterator<Integer> it;
      private boolean bMustSkip;
    
      public JumpIterator(List<Integer> list){
        this.it = list.iterator();
        this.bMustSkip = true;
      }
    
      private Iterator<Integer> myIterator() {
        if (bMustSkip && it.hasNext()) {
          it.next(); //Skipped
        }
        bMustSkip = false;
        return it;
      }  
    
      @Override
      public boolean hasNext() {
        //hasNext should be idempotent (should not modify the state)
        return myIterator().hasNext();
      }
    
      @Override
      public Integer next() {
        //If the user didn't check hasNext()
        // NoSuchElementException might be thrown,
        // which is interface-compliant, so we just don't care
        Integer nNext = myIterator().next();
        bMustSkip = true;
        return nNext;
      }
    }
    

    【讨论】:

    • 在您的解决方案中, hasNext() 并没有真正返回预期结果。例如,我们有列表{1, 2},当你在第一个位置并调用hasNext()时,它会返回true,但根据跳过逻辑没有下一个元素。
    • @zdlgrj 在第一个解决方案中,hasNext() 将首先返回 true(因为 1 是下一个元素。在调用 next 之后。它会返回 false,因为 it将被next()提前两次。
    • @zdlgrj 在第二个解决方案中,hasNext() 将在第一时间返回true,因为myIterator() 在第一次被调用时会推进it。只要调用next(),就会返回2,并将it 移到末尾。 myIterator() 不会做任何事情,因为 !it.hasNext()hasNext() 将返回 false。
    【解决方案4】:
    public class JumpIterator implements Iterator<Integer> {
      Iterator<Integer> iterator;
    
      public JumpIterator(Iterator<Integer> iterator) {
        this.iterator = iterator;
      }
    
      @Override
      public boolean hasNext() {
        return iterator.hasNext();
      }
    
      @Override
      public Integer next() {
        int res = iterator.next();
        if (iterator.hasNext()) {
            iterator.next();
        }
        return res;
      }
    
      @Override
      public void remove() {
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2016-01-23
      • 2020-10-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-09
      • 1970-01-01
      • 2011-08-06
      相关资源
      最近更新 更多