如何包装库 class 的迭代器以捕获 NoSuchElementException

How to wrap iterator of library class to catch NoSuchElementException

假设我有一个 class 持有一个可迭代的对象。现在出于某种原因,我想 "wrap" 这个迭代器,这样当没有更多的东西可以迭代时,我们不会因为 NoSuchElementException 而崩溃,而是返回 null。例如 ArrayList,这很容易,因为我可以在 class 上保存 index 属性。但是对于例如 TreeSet,它更棘手,因为据我所知没有办法使用索引。我如何使用 TreeSet 完成此操作?有什么方法可以在某处捕获异常吗?

我的 class 持有可迭代对象是:

public class MyClass{
    TreeSet<Integer> list = new TreeSet<Integer>();
   // Do something so that list.iterator() returns null when getting NoSuchElementException
}

我可以像这样使用它:

MyClass myObj = new MyClass();
Iterator myIter = myObj.iterator();
iterObj = myIter.next();
while(iterObj != null){
    //do stuff
}

当然我可以在 class 之外捕获异常,但是在多个地方这样做会导致大量的 try 和 catch 语句。

请不要告诉我我可以使用 foreach 循环,这在我的应用程序中是不可能的。

编辑:这就是我不能使用hasNext()的原因:

我有两个迭代器 listA 和 listB。

这里是原始算法:

    pA = listA.next(); // null if !hasNext()
    pB = listB.next(); // null if !hasNext()
    while(pA != null && pB != null){

        if(pA.docID == pB.docID){
            // do stuff
            pA = listA.next();
            pB = listB.next();
        }   

        else if(pA.docID < pB.docID){
            pA = listA.next();
        }   
        else{
            pB = listB.next();
        }   
    }   

我找不到使用 hasNext() 实现相同功能的方法。这是一个尝试:

while (listA.hasNext() && listB.hasNext()){
    pA = listA.next();
    pB = listB.next();
    if(pA.docID == pB.docID){
        // do stuff
    }
    else if(pA.docID < pB.docID){
        pA = listA.next();
    }   
    else{
        pB = listB.next();
    }       
}

但这显然不是同一个算法,只要我们没有 pA.docID == pB.docID,我们就会在 listAlistB 之一上迭代两次。有办法解决吗?

您可以使用 hasNext() 而不是直接调用 myIter.next()

if (myIter.hasNext ())
{
   iterObj = myIter.next();
   ...
}
else
{
   return null;
}

您似乎希望能够通过返回 null 而不是抛出 Exception 进行迭代。虽然这通常不像使用 Ravi 的解决方案那样受欢迎,但我尝试通过一般包装迭代器来发挥创造力并满足您的需求。

除非这是一项作业,否则请听从 Ravi 的建议。在 Java 中实现控制流是有原因的。通常不鼓励使用此类解决方法。

public class MyClass {

   public static class MyIterator<T> {
      Iterator<T> defaultIterator;

      public MyIterator(Iterator<T> defaultIterator) {
         this.defaultIterator = defaultIterator;
      }

      public T getNext() {
         try {
            if (defaultIterator.hasNext()) {
               return defaultIterator.next();
            }
         } catch (Exception e) {
            // Fall through
         }
         return null;
      }
   }

   public static void Main(String[] args) {
      TreeSet<Integer> list = new TreeSet<>();

      MyIterator<Integer> myIterator = new MyIterator<>(list.iterator());

      while (myIterator.getNext() != null) {
         // do stuff
      }
   }
}

如果您真的想在没有更多元素时捕获此异常,那么这是如何完成的示例之一:

public class MyClass { private final Set list = new TreeSet<>();

    public Iterator<Integer> iterator() {
        Iterator<Integer> it = list.iterator();
        return new Iterator<Integer>() {
            @Override
            public boolean hasNext() {
                return it.hasNext();
            }

            @Override
            public Integer next() {
                try {
                    return it.next();
                } catch (NoSuchElementException ignored) {
                    return null;
                }
            }
        };
    }

    public static void main(String... args) {
        MyClass myObj = new MyClass();
        Iterator<Integer> myIter = myObj.iterator();
        Integer iterObj = myIter.next();
        while (iterObj != null) {
            //do stuff
        }
    }
}

但我强烈建议您在从迭代器中检索该元素之前检查存在的元素:

Iterator<Integer> it = muObject.iterator();

while(it.hasNext()) {
    Integer value = it.next:
    // do stuff
}