Agrégée d'exécution des exceptions en Java 8 flux
Disons que j'ai une méthode qui renvoie une exception d'exécution. Je suis à l'aide d'un Stream
d'appeler cette méthode sur des éléments dans une liste.
class ABC {
public void doStuff(MyObject myObj) {
if (...) {
throw new IllegalStateException("Fire! Fear! Foes! Awake!");
}
//do stuff...
}
public void doStuffOnList(List<MyObject> myObjs) {
try {
myObjs.stream().forEach(ABC:doStuff);
} catch(AggregateRuntimeException??? are) {
...
}
}
}
Maintenant, je veux tous les éléments de la liste à traiter, et aucune des exceptions d'exécution sur des éléments individuels pour être rassemblées dans un "agrégat" runtime exception qui sera lancé à la fin.
Dans mon code, je fais de la 3e partie des appels d'API qui peut lancer des exceptions d'exécution. Je veux faire en sorte que tous les éléments sont traités et toutes les erreurs signalées à la fin.
Je ne peux penser à quelques façons de pirater ce, comme une map()
fonction qui récupère et retourne l'exception (..frisson..). Mais est-il originaire façon de le faire? Si non, est-il une autre façon de mettre en œuvre proprement?
- Cela se sent comme un abus du mécanisme d'exception. Quel est votre réel de cas d'utilisation ici? La validation d'un ensemble d'opérations et de rendre compte de ce qui a échoué?
- pas tout à fait. Je fais de la 3e partie des appels d'API qui peut lancer des exceptions d'exécution. Tout ce que je veux faire est de vous assurer que tous les éléments sont traités et toutes les erreurs signalées à la fin.
- Avez-vous vraiment besoin d'utiliser les flux? C'est trivial sans elle.
- Je sais, droit? Mais je m'attendais à utiliser
parallelStream
finalement. - Mon stream-fu n'est pas trop fort pour vous donner une belle réponse, mais basé sur cette discussion sur les cours d'eau et les exceptions un flux en fonction de la solution est au moins un peu douteuses.
Vous devez vous connecter pour publier un commentaire.
Dans ce cas simple où le
doStuff
méthode estvoid
et vous ne se soucient que les exceptions, vous pouvez garder les choses simples:Toutefois, si vos besoins sont plus complexes et vous préférez vous en tenir avec la bibliothèque standard,
CompletableFuture
peut servir à représenter "soit le succès ou l'échec" (quoique avec certaines verrues):Il y a déjà quelques implémentations de
Try
monade pour Java. J'ai trouvé mieux java8-monades de la bibliothèque, par exemple. En l'utilisant, vous pouvez écrire dans le style suivant.Supposons que vous souhaitez mapper vos valeurs et à suivre toutes les exceptions:
Laissez-nous un peu d'entrée:
Maintenant, nous pouvons cartographier à la réussite de la tente et passer à votre méthode, puis recueillir avec succès traité les données et les échecs séparément:
Après que vous pouvez traiter les lauréats:
Et de faire quelque chose avec toutes les exceptions:
La sortie est:
Personnellement, je n'aime pas la façon dont cette bibliothèque est conçue, mais probablement il sera adapté pour vous.
Voici un gist avec un exemple complet.
Voici une variation sur le thème de la cartographie à des exceptions.
Commencer avec votre
doStuff
méthode. Notez que ceci est conforme à l'interface fonctionnelleConsumer<MyObject>
.Maintenant écrire une fonction d'ordre supérieur qui encapsule cette et fait de cette dans une fonction qui pourrait ou ne pourrait pas renvoyer une exception. Nous voulons appeler cela de
flatMap
, donc la façon dont "pourrait ou ne pourrait pas" s'exprime par le retour d'un flux contenant de l'exception ou un vide de flux. Je vais utiliserRuntimeException
que le type d'exception ici, mais bien sûr, il pourrait être n'importe quoi. (En fait, il pourrait être utile d'utiliser cette technique avec les exceptions).Maintenant réécrire
doStuffOnList
à utiliser à l'intérieur d'un flux:RuntimeException
de l'ordre supérieur de la fonction et l'utilisation demap()
au lieu deflatMap()
?La seule voie possible que je peux imaginer est à la carte des valeurs dans une liste à une monade, qui va représenter le résultat de votre traitement de l'exécution (soit le succès de la valeur ou de l'échec avec throwable). Et ensuite, pliez vos flux dans un seul résultat avec la liste agrégée de valeurs ou d'une exception avec la liste de la suppression de la procédure précédente.
Résultat de la mise en œuvre peut varier, mais je pense que vous obtenez l'idée.
someValue
un paramètre de processus? Si oui, pourriez-vous résoudre ce problème s'il vous plaît?SomeType result
puis un traitement est fait oùlistItem
est converti enresult
et puis vous revenezResult.success(result)
?