web-dev-qa-db-fra.com

Java8: résultat stream findFirst

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.

14
Sunflame

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);
14
Sergii Bishyr

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)
8
Eugene

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.

enter image description here

2
holi-java