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

时间:2018-02-03 17:33:39

标签: java iterator nosuchelementexception

假设我有一个类,它持有一个可迭代的对象。现在由于某种原因,我想“包装”这个迭代器,这样当没有什么可以迭代时,而不是因为NoSuchElementException而崩溃,我们将返回null。例如ArrayList,这很容易,因为我可以在我的班级上保存index属性。但是例如TreeSet,它更棘手,因为据我所知,使用索引是没有办法的。如何使用TreeSet完成此操作?有没有办法在某个地方捕捉异常?

我持有iterable的类是:

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
}

当然我可以在类之外捕获异常,但是在多个地方这样做会导致很多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();
    }       
}

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

3 个答案:

答案 0 :(得分:1)

您似乎希望能够通过返回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
      }
   }
}

答案 1 :(得分:1)

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

public class MyClass {         private final Set list = new TreeSet&lt;&gt;();

    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检索此元素之前检查现有元素:

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

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

答案 2 :(得分:0)

您可以使用hasNext()代替直接调用myIter.next()

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