2016-06-10 42 views
0

我实现一个Iterator它利用另一个Iterator,它的我不知道,它是否支持remove()方法还是不行。Java异常Iterator的合同删除

考虑下面的边缘情况:底层迭代器支持remove()和我的迭代器next()尚未被调用。

我是否违反了合同的接口,如果我的remove()在这种情况下–的IllegalStateException而不是UnsupportedOperationException抛出–?
(只要next()被调用,底层remove()可以调用,这将引发相应的UnsupportedOperationException。)

如果是这样,我怎么能修改我的代码来检查底层迭代器是否支持remove()与否?


一个例子:

<T> Iterator<T> getSetViewIterator(Collection<T> collection) { 

    Iterator<T> uniqueItr = new HashSet<>(collection).iterator(); 

    return new Iterator<T>() { 
     private T current = null; 
     private boolean hasRemoved = true; 

     @Override 
     public boolean hasNext() { 
      return uniqueItr.hasNext(); 
     } 

     @Override 
     public T next() { 
      if(!hasNext()) 
       throw new NoSuchElementException(); 

      hasRemoved = false; 

      return current = uniqueItr.next(); 
     } 

     @Override 
     public void remove() { 
      if(hasRemoved) 
       throw new IllegalStateException(); 

      for(Iterator<T> iterator = collection.iterator(); iterator.hasNext();) { 
       if(iterator.next().equals(current)) 
        iterator.remove(); 
      } 

      hasRemoved = true; 
     } 
    }; 
} 

(。对于我们而言,我们可以假定,传递的集合不包含null

+0

这两个例外都是在写得很好的应用程序中永远不会发生的,所以在实践中我看不到这个问题。 – biziclop

+0

授予,但作为一个完美主义者,它会*使我感到厌烦,'remove()'改变它的异常。我相信它应该总是抛出一个'UnsupportedOperationException',如果底层的Iterator不支持它 - 我只是不知道如何实现这个... – triangular

+0

那么,在这种情况下,我会说你应该记住你是否已经抛出了一个ISE,并且继续扔掉它以用于剩余的物体的寿命。我知道这不是你想要的,但它是一致的。 – biziclop

回答

2

每您链接到文件,这两种例外情况是可以接受的对于remove方法,以及在next之前呼叫remove的情况被明确提及,并且允许投掷IllegalStateException

对于不支持remove,总是抛出UnsupportedOperationException迭代器是一样扔在非法状态的IllegalStateExceptionremovenext之前,第二removenext),只抛出其他异常的有效状态(第一为有效在next之后的remove)。这两种例外均适用于处于无效状态的呼叫 - 因为状态无效且操作不受支持。

你的包裹迭代器的工作原理恰到好处 - 它检查无效状态,然后委托给一个内部迭代器,然后可能会引发其支持的操作异常。您的迭代器不需要知道内部迭代器是否支持remove,因为如上所述,在非法状态下,这两个异常都是有效的响应。

+0

这也是我的理由 - 我只是不喜欢“remove”的例外情况,但我想我必须忍受它。 – triangular