Java 8 Ruisseaux et essayer avec des ressources
J'ai pensé que le flux de l'API était là pour rendre le code plus facile à lire.
J'ai trouvé quelque chose d'assez ennuyeux. Le Stream
interface (java.util.stream.Stream
) s'étend le AutoClosable
interface (java.lang.AutoCloseable
)
Donc, si vous voulez fermer correctement votre flux, vous devez utiliser l'essayer avec des ressources.
Listing 1. Pas très joli, les flux ne sont pas fermées.
public void noTryWithResource() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
@SuppressWarnings("resource") List<ImageView> collect = photos.stream()
.map(photo -> new ImageView(new Image(String.valueOf(photo)))).collect(Collectors.<ImageView>toList());
}
Listing 2. Avec 2 imbriquées à l'essayer 🙁
public void tryWithResource() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
try (Stream<Integer> stream = photos.stream()) {
try (Stream<ImageView> map = stream
.map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
}
}
}
Listing 3. Comme map
renvoie un flux de données, à la fois la stream()
et la map()
fonctions doivent être fermées.
public void tryWithResource2() {
Set<Integer> photos = new HashSet<Integer>(Arrays.asList(1, 2, 3));
try (Stream<Integer> stream = photos.stream();
Stream<ImageView> map = stream
.map(photo -> new ImageView(new Image(String.valueOf(photo))))) {
List<ImageView> collect = map.collect(Collectors.<ImageView>toList());
}
}
L'exemple que je donne n'a pas de sens. J'ai remplacé Path
à des images jpg avec Integer
, pour le bien de l'exemple. Mais ne laissez pas vous distraire par ces détails.
Quelle est la meilleure façon de se promener avec ces auto caisses de flux.
Je dois dire que je ne suis pas satisfait de l'un des 3 options je l'ai montré.
Qu'en pensez-vous? Existe-il encore d'autres solutions élégantes?
- Vous n'avez pas eu syntaxique raison de nid essayer dans essayer.
- double possible de Pourquoi est-Java 8 classe de Flux AutoCloseable?
Vous devez vous connecter pour publier un commentaire.
Vous utilisez
@SuppressWarnings("resource")
qui sans doute supprime un avertissement sur un ouvert de ressources. Ce n'est pas l'un des avertissements émis parjavac
. Des recherches sur le Web semblent indiquer que Eclipse, émet des alertes si unAutoCloseable
est laissée ouverte.C'est un avertissement raisonnable selon la Java 7 spécification qui introduit
AutoCloseable
:Cependant, la Java 8 spécification pour
AutoCloseable
a été assouplies afin de supprimer les "doit être fermé" de la clause. Il dit maintenant, en partie,Cette question a été largement débattue au sein de la Lambda groupe d'experts; ce message résume la décision. Entre autres choses, il mentionne les changements à la
AutoCloseable
spécification (cité ci-dessus) et laBaseStream
spécification (cité par d'autres réponses). Il mentionne également la nécessité éventuelle d'adapter l'Éclipse inspecteur de code pour le changement de sémantique, sans doute pas à émettre des avertissements sans condition pourAutoCloseable
objets. Apparemment, ce message n'a pas obtenir de l'Éclipse gens ou qu'ils n'ont pas changé encore.En résumé, si l'Éclipse mises en garde sont à la pointe vous en pensant que vous devez fermer tous les
AutoCloseable
objets, c'est incorrect. Uniquement un certain nombre deAutoCloseable
les objets doivent être fermés. Eclipse doit être corrigé (si ce n'est pas déjà le cas) de ne pas émettre des mises en garde pour tous lesAutoCloseable
objets.Vous avez seulement besoin de fermer les Ruisseaux si le flux doit faire tout le nettoyage de lui-même, habituellement I/O. Votre exemple utilise un HashSet de sorte qu'il n'a pas besoin d'être fermé.
de la Flux javadoc:
Donc dans votre exemple, cela devrait fonctionner sans problème
MODIFIER
Même si vous avez besoin de nettoyer les ressources, vous devriez être en mesure d'utiliser un try-with-ressource. Faisons semblant de croire que vous êtes la lecture d'un fichier où chaque ligne du fichier est un chemin vers une image:
“Fermer” signifie “qui peut être fermé”, et non “doit être fermé”.
Qui était vrai dans le passé, par exemple, voir
ByteArrayOutputStream
:Et qui est vrai aujourd'hui pour
Stream
s où les la documentation précise:Donc, si un outil de vérification génère de faux avertissements, c'est un problème de l'outil de vérification, pas de l'API.
Notez que même si vous voulez ajouter de la gestion des ressources, il n'est pas nécessaire de nid
try
consolidés. Tandis que le suivant est suffisant:vous pouvez également ajouter le secondaire
Stream
à la gestion des ressources sanstry
:Il est possible de créer une méthode utilitaire qui se ferme de manière fiable les flux avec un try-with-ressources-déclaration.
C'est un peu comme essayer enfin c'est un expression (ce qui est le cas par exemple Scala).
(Puisque les ressources qui doivent être fermés souvent aussi de lancer des exceptions lorsqu'ils sont affectés à la non-exécution des exceptions sont enveloppés dans des exceptions d'exécution, en évitant la nécessité d'une méthode distincte qui le fait.)
Avec cette méthode, l'exemple de la question ressemble à ceci:
C'est utile dans les situations où la fermeture du flux est nécessaire, comme lors de l'utilisation de
Files.lines
. Il aide aussi quand vous devez faire un double "fermer", comme dans votre exemple, Listing 3.Cette réponse est une adaptation d'une vieille réponse à une question similaire.