我已经实现了一个定制的java.util.Iterator,它使用了一个资源,该资源应该在最后使用close()
方法释放。该资源可以是java.sql.ResultSet、java.io.InputStream等...
public interface CloseableIterator<T> extends Iterator<T>
{
public void close();
}
一些使用这个迭代器的外部库可能不知道它必须被关闭。例如:
public boolean isEmpty(Iterable<T> myiterable)
{
return myiterable.iterator().hasNext();
}
在这种情况下,有没有办法关闭这个迭代器?
***************我会给予大家一个(+1)。当hasNext()**返回false时,我已经关闭了Iterator。我的问题是当循环迭代在最后一次迭代之前中断时,如我的示例所示。
8条答案
按热度按时间soat7uwm1#
创建一个自定义迭代器,实现AutoCloseable interface
然后在try with resource statement中使用这个迭代器。
无论发生什么情况,此模式都会关闭底层资源:- 在语句完成之后-并且即使抛出异常
最后,清楚地说明这个迭代器必须如何使用。
如果你不想把关键时刻交给别人,那就使用“推”策略。Java 8 lambda:
zvms9eto2#
在你的实现中,如果迭代器耗尽,你可以自己关闭它。
并明确记录:
例如:
顺便说一句,你可以实现Iterable并使用增强的for循环。
hyrbngr73#
问题是最后的条件。我们经常迭代一个完整的集合或数据集,所以我们现在 * 在最后 *,没有数据可供读取。
但是如果我们在到达End Of Data之前设置一个break,迭代器就不会结束,也不会关闭。
一种解决方法是在构造过程中将数据源的内容缓存在迭代器中,然后关闭资源。因此迭代器不会在打开的资源上工作,而是在缓存的数据上工作。
xam8gpfp4#
你可以在终结器中关闭它,但它不会给予你想要的行为。只有当垃圾回收器要清理对象时,才会调用终结器,因此资源可能保持打开状态。更糟糕的是,如果有人占用了你的迭代器,它将永远不会关闭。
有可能在第一次调用hasNext()并返回false时关闭流。这仍然不能保证做到这一点,因为有些人可能只迭代第一个元素,而不再为此费心。
实际上,我认为在处理外部库时,您需要自己管理它。您将对使用iterable的方法进行这些调用,那么为什么不在完成后自己关闭它呢?资源管理不是您可以强加给不了解任何更好的外部库的东西。
v8wbuo2f5#
如果可能,将迭代器 Package 在Stream中,这将给予您可以访问流的
onClose
方法。然后你应该把你的关闭逻辑移到那个方法中,并在那里做你的清理工作。示例:
f5emj3cl6#
只需定义自己的Iterator子接口,其中包含一个close方法,并确保使用该方法而不是常规Iterator类。例如,创建以下接口:
然后一个实现可能看起来像这样:
fquxozlt7#
在我的一个项目中,我也遇到了类似的问题,使用了像对象流这样的迭代器。为了覆盖迭代器没有完全消耗的时间,我还需要一个close方法。最初,我只是扩展了Iterator和Closable接口,但深入挖掘一下,java 1.7中引入的try-with-resources语句,我认为提供了一种实现它的整洁方法。
您扩展了Iterator和AutoCloseable接口,实现了Close方法,并在try-with-resources中使用了Iterator。一旦迭代器超出范围,运行时将为您调用close。
https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
举个例子
接口:
public interface MyIterator<E> extends Iterator<E>, AutoCloseable { }
public class MyIteratorImpl实现MyIterator {
{\fnSimHei\bord1\shad1\pos(200,288)}
下面是一个使用try -with-resource的例子:
public class MyIterator {
{\fnSimHei\bord1\shad1\pos(200,288)}
vaqhlq818#
根据合同,迭代器不需要关闭,所以你不能实现它需要更多的东西给用户。
我使用的一个解决方案是要求将关闭操作调度到“environment”并由“environment”执行。例如,在Web服务器中,我在请求属性中保存了一个可关闭的堆栈。有一个servlet过滤器,它基本上在请求端关闭堆栈中的所有可关闭对象。在这样的环境中,您可以在打开ClosableIterator时立即将其添加到该堆栈中,用户在请求处理的上下文中使用该对象,并且在请求结束时,过滤器关闭要关闭的内容。
另一种解决方案是将上次活动的时间戳与对象本身一起保存。这里有一个可关闭的列表。线程可以周期性地迭代列表以收集不活动/超时的可关闭项来关闭被放弃的可关闭项。
此外,你可以改变主意,从基于拉的方法转向基于推的方法。你可以创建一个Observable,而不是创建一个Iterator。