迭代器删除的Java异常契约

迭代器删除的Java异常契约,java,exception,collections,Java,Exception,Collections,我正在实现一个,它使用另一个迭代器,我不知道它是否支持remove()方法 考虑以下边缘情况:底层迭代器不支持remove(),对于我的迭代器next()尚未调用 如果我的remove()抛出一个IllegalStateException而不是UnsupportedOperationException,我是否违反了接口约定? (只要调用了next(),就可以调用底层的remove(),这将抛出相应的UnsupportedOperationException) 如果是这样,我如何重构代码以检查底层

我正在实现一个,它使用另一个迭代器,我不知道它是否支持
remove()
方法

考虑以下边缘情况:底层迭代器不支持
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;
        }
    };
}
迭代器getSetViewIterator(集合){
迭代器uniqueItr=新哈希集(集合).Iterator();
返回新的迭代器(){
专用T电流=零;
私有布尔hasRemoved=true;
@凌驾
公共布尔hasNext(){
返回uniqueItr.hasNext();
}
@凌驾
公共交通工具{
如果(!hasNext())
抛出新的NoTouchElementException();
hasRemoved=false;
返回电流=uniqueItr.next();
}
@凌驾
公共空间删除(){
如果(已删除)
抛出新的非法状态异常();
for(Iterator Iterator=collection.Iterator();Iterator.hasNext();){
if(迭代器.next().equals(当前))
iterator.remove();
}
hasRemoved=true;
}
};
}

(出于我们的目的,我们可以假设传递的集合不包含
null

根据您链接到的文档,这两种异常都适用于
remove
方法,并且明确提到了在
next
之前调用
remove
的情况,并允许抛出
非法状态异常

对于不支持
remove
的迭代器,始终抛出
UnsupportedOperationException
与在非法状态下抛出
IllegalStateException
一样有效(
remove
next
之前,第二个
remove
next
之后),并且只在有效状态下抛出另一个异常(第一次
删除
之后
下一次
)。这两种异常都适用于处于无效状态的调用,因为该状态无效且不支持该操作


您的包装迭代器工作正常-它检查无效状态,然后委托给内部迭代器,该迭代器可能会抛出其不受支持的操作异常。您的迭代器不需要知道内部迭代器是否支持删除,因为如上所述,在非法状态下,这两个异常都是有效的响应。

根据您链接的文档,这两个异常对于
删除方法都是可接受的,并且明确提到了在
next
之前调用
remove
的情况,并允许抛出
IllegalStateException

对于不支持
remove
的迭代器,始终抛出
UnsupportedOperationException
与在非法状态下抛出
IllegalStateException
一样有效(
remove
next
之前,第二个
remove
next
之后),并且只在有效状态下抛出另一个异常(第一次
删除
之后
下一次
)。这两种异常都适用于处于无效状态的调用,因为该状态无效且不支持该操作


您的包装迭代器工作正常-它检查无效状态,然后委托给内部迭代器,该迭代器可能会抛出其不受支持的操作异常。您的迭代器不需要知道内部迭代器是否支持remove,因为如上所述,在非法状态下,两个异常都是有效的响应。

这两个异常都是在编写良好的应用程序中不应该出现的类型,因此我在实践中看不到有太多问题。诚然,但作为一个完美主义者,它确实让我感到厌烦,
remove()
更改其异常。我认为,如果底层迭代器不支持它,它应该总是抛出一个
UnsupportedOperationException
,我只是不知道如何实现这一点……在这种情况下,我想说,你应该记住你是否已经抛出了一个ISE,并在对象的剩余生命周期中一直抛出它。我知道这不是你想要的,但它是一致的。这反过来肯定会违反合同,因为在(成功的)
next
之后,没有理由抛出
IllegalStateException
。你可以随时抛出
IllegalStateException
,你可以定义自己的合同。一旦你进入非法状态,就没有义务仅仅因为有人调用了
next()
就退出它。物理上不可能的一件事是,即使在第一个
next()
之前,底层迭代器总是抛出UOE。这两种异常都是在编写良好的应用程序中永远不会发生的,因此我在实践中看不到有太多的问题。诚然,作为一个完美主义者,这确实让我很恼火,
remove()
更改其异常。我认为,如果底层迭代器不支持它,它应该总是抛出一个
UnsupportedOperationException
,我只是不知道如何实现这一点……在这种情况下,我想说,你应该记住你是否已经抛出了一个ISE,并在对象的剩余生命周期中一直抛出它。我知道这不是你想要的,但这是一贯的。这反过来肯定会违反合同,不是吗