Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/363.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在foreach循环中正确处理NoTouchElementException?_Java_Iterator_Loops - Fatal编程技术网

Java 在foreach循环中正确处理NoTouchElementException?

Java 在foreach循环中正确处理NoTouchElementException?,java,iterator,loops,Java,Iterator,Loops,当迭代器引发NoTouchElementException并停止循环执行时,为什么foreach循环不考虑 让我解释一下 通常,迭代器需要提供两个重要的方法:hasNext和next。如果没有更多的元素可迭代,则下一个方法可以引发NoTouchElementException。hasNext方法更像是一个语法建议,只是为了让代码更好一点。重要的方法是next,这是一种应该做任何工作的方法,如果有的话,但不是hasNext,它需要在没有假设hasNext已经被预先调用的情况下实现 让我们假设我们有

当迭代器引发NoTouchElementException并停止循环执行时,为什么foreach循环不考虑

让我解释一下

通常,迭代器需要提供两个重要的方法:hasNext和next。如果没有更多的元素可迭代,则下一个方法可以引发NoTouchElementException。hasNext方法更像是一个语法建议,只是为了让代码更好一点。重要的方法是next,这是一种应该做任何工作的方法,如果有的话,但不是hasNext,它需要在没有假设hasNext已经被预先调用的情况下实现

让我们假设我们有以下情况:

final Iterator<String> bogusIt01 = new Iterator<String>() {

    public boolean hasNext() {
        return true;
    }

    public String next() {
        throw new NoSuchElementException("no such element");
    }

    public void remove() {
        throw new UnsupportedOperationException("cannot remove element");
    }

};

final Iterable<String> bogusPr01 = new Iterable<String>() {

    public Iterator<String> iterator() {
        return bogusIt01;
    }

};

for (@SuppressWarnings("unused") String string:bogusPr01) {
    // pass
}
这样的设计是不可能的,尽管对我来说很有意义

有更好的方法吗?

来自Javadoc for

如果迭代包含更多元素,则返回true。(换句话说,如果next()将返回元素而不是引发异常,则返回true。)

一般来说,如果您未能按照指定的API进行操作,JVM不会试图猜测它应该做什么,也不会执行变通方法。相反,它将生成您得到的异常或错误

如果您正在包装一个可能导致异常的迭代器,您应该抛出该异常,或者如果您觉得最好假装它从未发生过(这在IMHO中不太可能),那么您必须在调用next()之前检查这一点

来自Javadoc的

如果迭代包含更多元素,则返回true。(换句话说,如果next()将返回元素而不是引发异常,则返回true。)

一般来说,如果您未能按照指定的API进行操作,JVM不会试图猜测它应该做什么,也不会执行变通方法。相反,它将生成您得到的异常或错误

如果您正在包装一个可能导致异常的迭代器,您应该抛出该异常,或者如果您觉得最好假装它从未发生过(这在IMHO中不太可能),那么您必须在调用next()之前检查这一点


此代码的问题在于,如果对
hasNext
的上一次调用返回true,则
迭代器不应从
getNext
引发
NoTouchElementException
。你可以考虑这样做:

    public boolean hasNext() {
        return iterator1.hasNext();
    }

    public Object next() {
        if (!iterator1.hasNext()) {
            throw new NoSuchElementException("no such element");
        }

        Object nextValue = iterator1.next();

        try {
            // do something that could raise exception
        } catch (Exception e) {
            return this.next();
        }

        return productValue;
    }

    public void remove() {
        throw new UnsupportedOperationException("cannot remove element");
    }
  • hasNext
    中,从底层迭代器获取下一个适当的元素,并将其缓存,直到下一次调用
    next
    。从
    next
    返回缓存的值。如果缓存的值为null,则不会调用
    hasNext
    ,然后可以适当地抛出NSEE
  • 您可能需要考虑的另一个选项是使用番石榴的<代码>迭代。转换或<代码>列表。转换< /代码>。这是为了获取一个

    Iterable
    ,并对每个元素执行一些转换。您可以为任何无法转换的值返回
    null
    ,并使用
    谓词执行
    Iterables.filter
    。notNull
    谓词
    删除非null元素

    使用番石榴,上述代码为:

    Function<A, B> myFunction = new Function<A,B>(){
       public B apply(A input){
          try{ // do work
             return new B();
          catch(Exception e){ return null; }          
       }
    }
    
    Iterable<A> inputList = ...;
    Iterable<B> newList = Iterables.filter(
           Iterables.transform(inputList, myFunction), 
           Predicates.notNull());
    
    for (B b : newList)...
    
    函数myFunction=新函数(){
    公共B应用(A输入){
    试着做工作
    返回新的B();
    catch(异常e){returnnull;}
    }
    }
    Iterable inputList=。。。;
    Iterable newList=Iterables.filter(
    转换(inputList,myFunction),
    谓词。notNull());
    对于(B:新列表)。。。
    
    <代码> <代码>的问题是,<代码> Iterator <代码>不应该从 GETNeX中抛出<代码> NouChelEngultExvuts<代码> >如果之前调用<代码>下一次返回true。您可以考虑这样做:

        public boolean hasNext() {
            return iterator1.hasNext();
        }
    
        public Object next() {
            if (!iterator1.hasNext()) {
                throw new NoSuchElementException("no such element");
            }
    
            Object nextValue = iterator1.next();
    
            try {
                // do something that could raise exception
            } catch (Exception e) {
                return this.next();
            }
    
            return productValue;
        }
    
        public void remove() {
            throw new UnsupportedOperationException("cannot remove element");
        }
    
  • hasNext
    中,从底层迭代器获取下一个适当的元素,并将其缓存到下一次调用
    next
    之前。从
    next
    返回缓存值。如果缓存值为null,则不会调用
    hasNext
    ,然后可以适当地抛出NSEE
  • 您可能需要考虑的另一个选项是使用番石榴的<>代码> Itdiabor。转换<代码> >代码>列表。转换<代码> >。

    谓词.notNull
    谓词
    删除非null元素

    使用番石榴,上述代码为:

    Function<A, B> myFunction = new Function<A,B>(){
       public B apply(A input){
          try{ // do work
             return new B();
          catch(Exception e){ return null; }          
       }
    }
    
    Iterable<A> inputList = ...;
    Iterable<B> newList = Iterables.filter(
           Iterables.transform(inputList, myFunction), 
           Predicates.notNull());
    
    for (B b : newList)...
    
    函数myFunction=新函数(){
    公共B应用(A输入){
    试着做工作
    返回新的B();
    catch(异常e){returnnull;}
    }
    }
    Iterable inputList=。。。;
    Iterable newList=Iterables.filter(
    转换(inputList,myFunction),
    谓词。notNull());
    对于(B:新列表)。。。
    
    以下内容如何

    import java.util.Iterator;
    
    public class BreakingIterator<T> implements Iterator<T> {
    
        private Iterator<T> iterator;
        private T nextValue;
        private RuntimeException nextException;
    
        /* -------------------------------------------------------------------- */
    
        public BreakingIterator(Iterator<T> iterator) {
            this.iterator = iterator;
            this.nextValue = null;
            this.nextException = null;
        }
    
        /* -------------------------------------------------------------------- */
    
        public boolean hasNext() {
            if (this.iterator.hasNext()) {
                try {
                    this.nextValue = this.iterator.next();
                } catch (RuntimeException e) {
                    this.nextValue = null;
                    this.nextException = e;
    
                    return false;
                }
    
                return true;
            } else {
                return false;
            }
        }
    
        public T next() {
            if (this.nextException != null) {
                throw this.nextException;
            } else {
                return this.nextValue;
            }
        }
    
        public void remove() {
            this.iterator.remove();
        }
    
    }
    
    import java.util.Iterator;
    公共类BreakingIterator实现了迭代器{
    私有迭代器;
    私有下一价值;
    私有运行时异常nextException;
    /* -------------------------------------------------------------------- */
    公共中断迭代器(迭代器迭代器){
    this.iterator=迭代器;
    this.nextValue=null;
    this.nextException=null;
    }
    /* -------------------------------------------------------------------- */
    公共布尔hasNext(){
    if(this.iterator.hasNext()){
    试一试{
    this.nextValue=this.iterator.next();
    }捕获(运行时异常e){
    this.nextValue=null;
    this.nextException=e;
    返回false;
    }
    返回true;
    }否则{
    返回false;
    }
    }
    公共交通工具{
    if(this.nextException!=null)