关闭 java.util.Iterator

2022-09-01 07:27:16

我已经实现了一个自定义java.util.Iterator,使用一个资源,应该使用方法在最后发布。该资源可以是java.sql.ResultSetjava.io.InputStream等...close()

public interface CloseableIterator<T> extends Iterator<T>
  {
  public void close();
  }

使用此迭代器的某些外部库可能不知道必须关闭它。例如:

public boolean isEmpty(Iterable<T> myiterable)
 {
 return myiterable.iterator().hasNext();
 }

在这种情况下,有没有办法关闭这个迭代器?

更新:非常感谢当前的答案。我会给大家一个(+1)。我已经在 hasNext() 返回 false 时关闭了迭代器。我的问题是当循环迭代在最后一次迭代之前中断时,如我的示例所示。


答案 1

创建实现自动关闭接口的自定义迭代器

public interface CloseableIterator<T> extends Iterator<T>, AutoCloseable {
}

然后在 try with resource 语句中使用此迭代器。

try(CloseableIterator iterator = dao.findAll()) {
    while(iterator.hasNext()){
       process(iterator.next());
    }
}

无论发生什么情况,此模式都会关闭基础资源: - 在语句完成后 - 即使引发异常

最后,清楚地记录必须如何使用此迭代器。

如果不想委派关闭呼叫,请使用推送策略。例如。与 java 8 lambda:

dao.findAll(r -> process(r));

答案 2

在你的实现中,你可以自己关闭它,如果迭代器耗尽。

public boolean hasNext() {
       .... 
       if( !hasNext ) {
           this.close();
       }
       return hasNext;
 }

并清楚地记录:

当 hasNext() 返回 false 时,此迭代器将调用 close(),如果您需要在确保调用 close self 之前释放迭代器

例:

void testIt() {
     Iterator i = DbIterator.connect("db.config.info.here");
     try {
          while( i.hasNext() {
              process( i.next() );
          }
      } finally {
          if( i != null )  {
              i.close();
          }
      }
  }

顺便说一句,你可以在那里实现Iterable并使用增强的for循环。