Question Java 8 extrait les valeurs non nulles et non vides de HashMap


Laisser considérer un ci-dessous HashMap

HashMap<String, String> map = new HashMap<String, String>();

J'ai des valeurs dans la carte comme

map.put("model", "test");

Actuellement, si je veux obtenir de la valeur de la carte, je le fais

if(map!=null){
 if(map.get("model")!=null && !map.get("model").isEmpty()){
   //some logic
 }
}

Y at-il une meilleure approche dans Java 8 en utilisant Optional ou Lambdas pour atteindre la condition ci-dessus?


13
2017-11-08 22:55


origine


Réponses:


Vous ne savez pas pourquoi vous vérifiez si la carte est nulle, mais voici:

Optional.ofNullable(map)
    .map(m -> m.getOrDefault("model", "")) // Use an empty String if not present
    .filter(s -> !s.isEmpty())             // Filter all empty values
    .ifPresent(valueString -> {            // Check if value is present
        // Logic here
});

Ou en une seule ligne:

Optional.ofNullable(map).map(m -> m.getOrDefault("model", "")).filter(s -> !s.isEmpty()).ifPresent(valueString -> {
        // Logic here
});

Changement ifPresent à map si vous voulez retourner quelque chose; c'est-à-dire facultatif de ce que vous calculez.


6
2017-11-08 22:59



Tout d'abord, votre carte ne doit pas être nulle. Jamais. Il pourrait être vide, mais il n'y a aucune raison pour que ce soit nul. Cela élimine donc le premier contrôle nul.

Maintenant, malheureusement, Java ne dispose pas d'une telle méthode utilitaire, mais plusieurs bibliothèques couramment utilisées (apache commons, Guava, etc.) l'ont, ou vous pouvez l'écrire vous-même, donc cela devient:

String model = map.get("model");
if (!Strings.isEmptyOrNull(model)) {
    // do somthing
}

L'utilisation de l'option Facultatif pour envelopper une valeur nullable dans le cadre de votre logique est considérée comme un anti-modèle. Facultatif est conçu pour être utilisé comme type de retour. Je ne voudrais donc pas en parler ici.

Notez également que vous avez l'impression d'utiliser une carte pour stocker les attributs d'un objet. Si tel est le cas, envisagez de définir une classe réelle, avec des propriétés typées, au lieu d'utiliser une carte.


12
2017-11-08 23:02



Si vous êtes intéressé par un Optional approche,

Vous pouvez envelopper un map.get("model") valeur dans un Optional.ofNullable et faire le travail de filtrage par le Predicate<String>  value -> !value.isEmpty():

if (isNull(map)) { // import static java.util.Objects.isNull;
    return;        // to minimise nesting
}

Optional.ofNullable(map.get("model"))
        .filter(value -> !value.isEmpty())
        .ifPresent(value -> { ... });

2
2017-11-08 23:00



Si vous avez déclaré map comme indiqué dans votre exemple de code, il ne sera pas null et vous n'avez pas besoin de vérifier. Si vous voulez vous assurer, ajoutez une assertion:

assert map != null;

Étant donné que vous testez des chaînes vides, une approche possible consiste à utiliser la chaîne vide par défaut si la clé n'est pas présente:

if (!map.getOrDefault("model", "").isEmpty()) {
    ...
}

Je pense qu'il est dommage qu'il n'y ait pas de méthode ajoutée à Map qui retourne un Optional Plutôt qu'un null si la clé n'est pas présente. Quelque chose comme:

map.getOptional("model").filter(v -> !v.isEmpty()).ifPresent(v -> {
    ...
}

Alors que des options ont été ajoutées, les anciennes API ont été retravaillées pour ne plus tenir compte des méthodes qui renvoient null signifier "pas présent".


0
2017-11-08 23:14