La fermeture d'un java.util.Itérateur
J'ai mis en œuvre un custom java.util.Itérateur à l'aide d'une ressource qui devrait être publié à la fin à l'aide d'un close()
méthode. Cette ressource pourrait être un java.sql.ResultSet, un java.io.InputStream etc...
public interface CloseableIterator<T> extends Iterator<T>
{
public void close();
}
Certaines bibliothèques externes à l'aide de cet itérateur peut ne pas savoir qu'il doit être fermé. e.g:
public boolean isEmpty(Iterable<T> myiterable)
{
return myiterable.iterator().hasNext();
}
Dans ce cas, est-il un moyen de fermer cette itérateur?
Mise à jour: merci beaucoup pour les réponses actualisées . Je vais vous donner un (+1) pour tout le monde. Je fais déjà proche de l'Itérateur quand hasNext() renvoie la valeur false. Mon problème est que lorsque la boucle d'itération pauses avant la dernière itération comme il est montré dans mon exemple.
Vous devez vous connecter pour publier un commentaire.
Le problème est la condition à la fin. Souvent, nous itérer sur une collection complète ou ensemble de données, nous sommes donc à la fin pour le moment, il n'y a pas de données de gauche à lire.
Mais si nous fixons une pause hors de la boucle, avant d'avoir atteint la Fin Des Données, l'itérateur ne serait pas venu à une fin, et ne serait pas fermé.
Un moyen de sortir pourrait être de mettre en cache le contenu de la source de données dans l'itérateur au cours de la construction et de fermer la ressource. Si l'itérateur ne fonctionnerait pas sur les ressources ouvert, mais sur les données mises en cache.
Créer un itérateur qui mettent en œuvre les AutoCloseable interface
Et ensuite utiliser cet itérateur dans un essayez avec déclaration de ressources.
De ce modèle à proximité de la ressource sous-jacente quoi qu'il arrive:
- après la déclaration complète
- et même si une exception est levée
Enfin, clairement de quelle façon cet itérateur doit être utilisé.
Si vous ne souhaitez déléguer la proximité des appels, utiliser une stratégie "push". par exemple. avec java 8 lambda:
De la mise en œuvre que nous pouvons fermer votre auto, si lors de la iteratoror est épuisé.
Et de documenter clairement:
exemple:
Btw, vous pouvez pendant que vous y êtes, vous pourriez mettre en œuvre Itérable et utiliser l'interface de boucle.
Vous pourriez fermer dans un finaliseur mais il ne va pas vous donner le comportement que vous souhaitez. Votre finalizer est appelée que lorsque le garbage collector veut nettoyage de votre objet, de sorte que votre ressource peut rester ouverte. Pire, si quelqu'un détient sur votre itérateur, il ne serez jamais à fermer.
Il y a une possibilité de fermer le flux sur le premier appel à hasNext() retourne la valeur false. Ce n'est pas encore garanti de le faire, car quelqu'un peut itérer uniquement le premier élément et ne jamais la peine avec elle à nouveau.
Vraiment, je pense que vous aurez besoin pour gérer vous-même lorsque vous traitez avec une bibliothèque externe. Vous allez faire de ces appels à des méthodes qui utilisent l'itératif, alors pourquoi ne pas la fermer vous-même lorsque vous avez terminé? La gestion des ressources n'est pas quelque chose que vous pouvez simplement imposer une bibliothèque externe qui ne savent pas mieux.
Il suffit de définir votre propre sous-interface de l'Itérateur qui inclut une méthode close, et assurez-vous d'utiliser à la place régulière de la classe Iterator. Par exemple, créer cette interface:
Puis une mise en œuvre pourrait ressembler à ceci:
J'ai eu un problème similaire dans un de mes projets à l'aide d'un Itérateur comme un Objet de flux. Pour couvrir à la fois l'Itérateur n'est pas entièrement consommé, j'ai aussi besoin d'une méthode close.
Au départ, j'ai simplement étendu Itérateur et les Caisses d'interfaces, mais creuser un peu plus profond, le try-with-resources déclaration introduite dans java 1.7, j'ai pensé a fourni un bon moyen de le mettre en œuvre.
Vous étendre Itérateur et AutoCloseable interfaces, de mettre en œuvre la méthode de fermeture et d'utiliser l'Itérateur dans un try-with-resources.
Le moteur d'Exécution d'appeler à proximité pour vous une fois que l'Itérateur est hors de portée.
https://docs.oracle.com/javase/7/docs/api/java/lang/AutoCloseable.html
https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html
Par exemple
L'Interface:
public interface MyIterator<E> extends Iterator<E>, AutoCloseable {
}
De mise en Œuvre de celui-ci:`
public class MyIteratorImpl implémente MyIterator {
}
`
Et un exemple d'utilisation avec le try-with-ressource:
`
public class MyIteratorConsumer {
}
`
Si possible, enveloppez l'itérateur dans un Flux qui vous donnera l'accès à la
onClose
méthode des flux. Puis vous devez transférer vos proches logique dans la méthode et de faire votre nettoyage de là.Exemple: