Je veux savoir qu'il existe un moyen de se débarrasser de l'avertissement dans findFirst().get()
sans utiliser .orElse()
si je sais à 100% qu'il y a chaque fois un résultat, donc je n'y arrive jamais NoSuchElementException
. Par exemple, voyons le code suivant:
List<String> myList = new ArrayList<>();
myList.add("Test");
myList.add("Example");
myList.add("Sth");
String fisrstString = myList.stream().findFirst().get(); // here I surely get "Test"
Je ne sais pas comment les autres IDE traitent cela, mais mon IDE (IntelliJ) le traite comme un avertissement ('Optional.get()' without 'isPresent()'
). Je pense que probablement Je ne sais pas quand pouvez-vous obtenir NoSuchElementException
et quand non, ou je ne sais pas pourquoi. Je sais qu'il existe des moyens de résoudre cet avertissement (isPresent()
check, .orElse(something)
) mais avec du code inutile, donc je ne veux pas utiliser ces solutions parce qu'elles sont si inutiles. Avez-vous une idée de ce que je peux faire, ou expliquez comment cela est traité par theIDE?
Edit: Désolé pour NPE, son NoSuchElementException
J'ai eu cette erreur, mais je pense que la question est toujours disponible pour cela.
Eh bien, pour moi, la meilleure façon est d'utiliser la programmation fonctionnelle et de continuer à travailler avec facultatif. Ainsi, par exemple, si vous devez passer cette chaîne à un service, vous pouvez faire:
String fisrstString = myList.stream().findFirst().get();
service.doSomething(fisrstString);
Mais cela ne semble pas si bon. Au lieu de cela, vous pouvez utiliser les avantages de la programmation fonctionnelle et faire:
myList.stream().findFirst().ifPresent(service::doSomething);
D'abord, vous n'obtiendrez pas un NPE
, mais un NoSuchElementException
. Deuxièmement, c'est vous qui pourrait en être sûr; mais d'autres personnes pourraient venir et ne se rendent pas compte que cela ne ne lèvera pas d'exception.
Pour un projet sandbox - oui, vous ne vous en souciez pas et pouvez ignorer l'avertissement; pour le code de production, je ne le désactiverais pas (même si vous le pouviez).
Et le dernier point est que si vous êtes si sûr, pourquoi ne pas lever une exception?
orElseThrow(IAmSureThisWillNotHappenException::new)
Vous devriez utiliser le Optional
retourné par findFirst()
au lieu d'essayer d'obtenir sa valeur (s'il est réellement présent).
myList.stream()
.findFirst()
.ifPresent(/* consume the string here, if present */);
La méthode Optional.ifPresent
reçoit un Consumer
qui sera utilisé uniquement si le Optional
contient une valeur non nulle.
Le problème est que nous Java sont tellement habitués au paradigme impératif ... En particulier, nous sommes habitués à obtenir un objet et à pousser c'est-à-dire à une méthode:
String myString = "hello"; // getting an object here
System.out.println(myString); // pushing the object to System.out here
// (via the println method)
Avec le Optional
retourné par Stream.findFirst()
vous faisiez la même chose que ci-dessus:
String myString = myList.stream()
.findFirst()
.get(); // getting a string here
System.out.println(myString); // pushing the string here
D'un autre côté, le paradigme fonctionnel (y compris Optional
) fonctionne généralement dans l'autre sens:
myList.stream()
.findFirst()
.ifPresent(myString -> System.out.println(myString));
Ici, vous n'obtenez pas la chaîne, puis la poussez vers une méthode. Au lieu de cela, vous fournissez un argument à l'opération Optional
de ifPresent
et laissez l'implémentation de Optional
Poussez la valeur vers votre argument. En d'autres termes, vous tirez la valeur encapsulée par Optional
au moyen de l'argument de ifPresent
. ifPresent
utilisera alors cet argument Consumer
, uniquement si la valeur est présente.
Ce modèle de pull est très utilisé dans la programmation fonctionnelle et est très utile une fois que vous vous y êtes habitué. Cela exige simplement que nous, les développeurs, commencions à penser (et à programmer) différemment.
vous pouvez diffuser une liste vide sans problème, mais si vous essayez d'obtenir le 1er élément sur une liste vide, vous obtiendrez une NoSuchElementException
l'API Stream en est consciente, elle vous offre donc plusieurs façons de gérer cela:
Option1: orElse
vous pouvez retourner une valeur "par défaut" si aucun 1er élément n'est trouvé
String firstString = myList.stream().findFirst().orElse("Ups!");
Option2: orElseGet
vous pouvez utiliser un Supplier<String>
qui renvoie une chaîne si aucun 1er élément n'est trouvé
firstString = myList.stream().findFirst().orElseGet(mySupplier);
Option: orElseThrow
vous pouvez lever une exception si aucun 1er élément n'est trouvé
firstString = myList.stream().findFirst().orElseThrow(WhatTerribleFailException::new);
System.out.println(fisrstString);
[~ # ~] si [~ # ~] vous savez que votre Optional
n'est jamais vide, vous pouvez utiliser @SuppressWarnings
annotation comme ci-dessous:
@SuppressWarnings("ConstantConditions") String foo = Optional.of("bar").get();
Parfois Optional.get
Soulèvera un NullPointerException
, par exemple:
Optional<String> it = Optional.empty();
String foo = it.get();
// ^--- throws NullPointerException when this method is invoked
[~ # ~] donc [~ # ~] lorsque cette expression est utilisée, Intellij signalera une mise en garde inspection.
[~ # ~] si [~ # ~] vous souhaitez désactiver toutes les inspections de contrat, vous pouvez effectuer les actions suivantes: Paramètres -> Inspections -> décoché la Condition constante et exceptions option -> n'oubliez pas de cliquer sur le bouton Appliquer en bas pour enregistrer vos paramètres.
[~ # ~] si [~ # ~] vous ne voulez pas désactiver toutes les inspections de contrat sauf Optional.get()
les avertissements que vous pouvez effectuez les actions suivantes: Paramètres -> Inspections -> vérifié la Condition constante et exceptions option -> en bas à droite il y a un cadre pour configurer Optional.get()
avertissements -> n'oubliez pas de cliquez sur le bouton Appliquer en bas pour enregistrer vos paramètres.