【问题标题】:How do I refer to the current object in an iterator如何在迭代器中引用当前对象
【发布时间】:2011-07-06 22:49:21
【问题描述】:

我正在尝试在 TreeSet 中实现搜索方法。通过使用带有条件的迭代器,我希望能够遍历集合并打印与条件匹配的对象。然而,我现在这样做的方式是打印出后续对象而不是当前对象。 这是我目前所拥有的:

public void getDetails() {
        Iterator<Person> it = this.getPersonSet().iterator();
        System.out.println("Enter First Name");
        String first = in.next().toLowerCase();
        System.out.println("Enter Second Name");
        String last = in.next().toLowerCase();

        while (it.hasNext()) {
            if (it.next().getLast().toLowerCase().equals(last)) {
                Person p = it.next();
                System.out.println(p);
            }
        }

    }

任何帮助都会很棒

【问题讨论】:

    标签: java iterator


    【解决方案1】:

    这就是你想要做的:

    while (it.hasNext()) {
                Person p = it.next();
                if (p.getLast().toLowerCase().equals(last)) {
                    System.out.println(p);
                }
            }
    

    【讨论】:

    • 这不会跳过数组列表中的第一个对象吗? ://
    • @SrujanBarai - 不。 (字面意思是……它不会“跳过它”)
    • @StephenC 哦,是的,我实现了它,它没有跳过第一个对象,似乎迭代器一开始没有指向任何东西,然后it.next();上的下一个对象@
    • 那么你为什么期望它会跳过第一个对象呢?这不是迭代器的工作方式......根本。如果您希望此答案中的代码跳过某些内容,那不是它打算做的。 (也许你应该问你自己的问题,向我们展示你自己的代码版本,并清楚地解释问题是什么......)
    【解决方案2】:

    如何在迭代器中引用当前对象

    郑重声明,Iterator API 不允许您执行此操作。没有“当前”对象的概念。 Iterator.next() 方法为您提供下一个对象......然后继续。

    (ListIterator.previous() 和ListIterator.next() 方法是类似的。请注意,在ListIterator 的情况下,方法行为是根据表示被迭代序列中元素之前/之间/之后的位置的光标来记录的。 )

    解决方案是将调用it.next() 的结果分配给一个临时变量,如接受的答案所述。


    我不确定为什么设计者没有在 API 中包含“当前”对象的概念,但我可以想到几个原因:

    • 它会使典型的迭代器对象变大;即一个额外的字段来保存当前对象。
    • 这意味着 Iterator 类要实现更多 1 个方法。
    • 当前对象的概念与 ListIterator 接口中记录的“光标”模型不太吻合......并且由当前的 Iterator 设计暗示。
    • 存在迭代器“挂在”当前对象上的小问题,从而阻止它被 GC。
    • 大多数迭代器用例不需要当前对象。
    • 还有其他方法可以解决这个问题。

    听起来不错……

    【讨论】:

    • 我完全不明白为什么没有“当前”。一个非常基本的用途是在任何情况下想要异步比较当前值和下一个值。例如,如果修改了一个列表,索引可能不再指向您想要它指向的位置,因此显而易见的解决方案是迭代器.. 虽然这不允许比较值。呃。
    • @Thumbz - 嗯......请参阅我的答案,了解为什么“当前”通常不是一个好主意。 (为了其他人的方便而打破一些用例是不好的。)对于你的用例,考虑编写一个迭代器包装类,它添加一个 getCurrent() 方法......如果这可以为​​你简化事情。
    • 如果您查看迭代器的源代码,您的答案的第二部分没有任何内容是正确的。一个迭代器包含 2 个变量:int cursor 指向下一个元素,int lastRet 指向返回的最后一个元素。因此不需要额外的字段。这些是索引号而不是对象本身,因此迭代器不会以任何方式“挂在”当前对象上。游标模型用于解释迭代器的设计,而不是相反。这并不是因为 90% 的人不会使用它,你不必实施它。这只是糟糕的设计。
    • @Didii - 用于特定的迭代器实现。但是考虑一下这种方法是如何在链表中工作的……或者是惰性流的迭代器。当然,current() 方法对于某些类型的迭代器来说很容易,但对于其他迭代器来说却有问题。如果不考虑Iterator 的所有实现和所有用例,就不能称之为“糟糕的设计”。如果您想这样做,请随时 1) 进行研究,以及 2) 在另一个答案中列出您的发现。
    【解决方案3】:

    如果您需要现有的实现,可以使用来自Google Guava 或Apache Commons Collections 的实现。
    对于您的简单问题,其他答案更容易,但如果您需要传递迭代器并跟踪 next() 返回的最后一项,这些会有所帮助。

    这是一个使用 Guava 和 OP 代码的示例(假设 Person 确实有一个 String toLowerCase() 方法):

    import com.google.common.collect.PeekingIterator;
    import static com.google.common.collect.Iterators.peekingIterator;
    
    public void getDetails() {
        PeekingIterator<Person> it = peekingIterator(this.getPersonSet().iterator());
        System.out.println("Enter First Name");
        String first = in.next().toLowerCase();
        System.out.println("Enter Second Name");
        String last = in.next().toLowerCase();
    
        while (it.hasNext()) {
            // note the usage of peek() instead of next()
            if (it.peek().getLast().toLowerCase().equals(last)) {
                Person p = it.next();
                System.out.println(p);
            }
        }
    
    }
    

    【讨论】:

    • 最好展示一个小例子来说明如何在这种特定情况下使用这些迭代器,而不是简单地链接到它们。
    【解决方案4】:

    将对象的引用保存在单独的 var 中:

    Person current = it.next();
    current.methodOne();
    current.methodTwo();
    

    当你完成当前值后,下一个重新赋值

    ...
    // done? 
    current = it.next();
    

    在一个循环中看起来像:

    while( it.hasNext() ) { 
       Person current = it.next();
       current.doA();
       current.doB();
       current.doC();
     }
    

    【讨论】:

      【解决方案5】:

      next() 方法返回当前对象,如下所示:

      private class IterSinglyLinked implements SimpleIterator<T> {
          Element curr = head;        // next element to return
      
          public boolean hasNext() {
              return curr != null;
          }
      
          public T next() throws Exception {
              if (curr == null) throw new Exception("no more elements");
              T data = curr.data;
              curr = curr.next;
              return data;
          }
      }
      

      如果它返回下一个而不是当前的,将无法到达第一个

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-12-03
        • 2011-03-20
        • 1970-01-01
        • 2014-03-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多