web-dev-qa-db-fra.com

Utilisez Pojo ou Carte quand il y a un nombre fini de clés connues?

J'ai un ensemble de données avec des paires de la valeur clé, mais il n'y a qu'un ensemble de clés fini et connu, toute la clé doit toujours être présente sur ces données, et ils ont tous le même type pour la valeur. Cela a-t-il plus de sens d'utiliser un énumé pour la clé d'une carte (comme Map<SomeEnum, String>) ou faire une nouvelle classe pour la représenter? Les deux approches Can Travailler, mais je me demande qui a plus de sens.

Si ces données étaient en Json, cela pourrait ressembler à quelque chose comme ça.

{
  "alpha": "blah",
  "bravo": "blah blah",
  "charlie": "blah blah blah"
}

Mon instinct est que l'approche de la classe est meilleure. Mon raisonnement est que l'utilisation d'un Map est plus pour lorsque vous avez des clés ou des clés arbitraires qui seront inconnues au moment de la compilation. L'un des avantages d'une classe avec getters est que toutes les clés possibles sont juste là, elles sont des méthodes essentiellement. Cela rend le code plus "auto documentation" dans un sens. Le seul inconvénient de cette approche est qu'il y a plus de chaudière à écrire (ce qui peut être soulagé avec des éléments tels que les outils de génération de sources IDes).

Le code de l'approche de la classe serait quelque chose comme ça.

class Data {
  private final String alpha;
  private final String bravo;
  private final String charlie;
  // Constructor and getters omitted for brevity
}

Le code de l'approche de la carte serait quelque chose comme ça.

enum Key {
  ALPHA, BRAVO, CHARLIE
}
//...
Map<Key, String> data;
3
Captain Man

J'irais avec l'approche pojo (objet).

Les deux sont assez raisonnables. Mais lorsque vous regardez l'utilisation, l'approche objet est plus terres et claire.

Et plus important encore, il généralise mieux. Considérez si la valeur associée à l'un des noms n'était pas une chaîne?

Et si c'était un entier ou un tableau ou une autre énumération? Cela pourrait même être une autre structure (Pojo).


3
Lewis Pringle

Pourquoi ne pas utiliser les deux?

Vous pouvez créer un objet qui contient la clé identifiée avec précision (alpha, bravo et charlie dans votre cas).

Ensuite, incluez une carte qui contient tous les champs supplémentaires.

Utiliser Jackson, vous pouvez le faire facilement.

Cela ressemblerait à ceci:

public class Data {
    private final String alpha;
    private final String beta;
    private final String charlie;

    private final Map<String, Object> extraFields;

    // constructor, getters and setters

    @JsonAnyGetter
    public Map<String, Object> getExtraFields(){
           return extraFields;
    }

    @JsonAnySetter
    public void setExtraField(String key, Object value) {
           extraFields.put(key, value);
    }

}

Si vous devez vraiment choisir entre l'approche de la carte et le pojo, je vais certainement aller pour Pojo.

Vous pourrez avoir plus de structure complexe (delta pourrait être un objet de type SubData). Cette structure sera ensuite fortement typée et vous n'aurez pas à gérer plusieurs casting. De cette façon, vous réduisez les possibilités d'erreur d'exécution et améliorez la lisibilité du code.

2
Grégory Elhaimer

Cela dépend des modèles d'utilisation.

Je préférerais généralement la version Pojo car elle est plus propre, plus sûre et plus facile pour l'optimiseur Hotspot.

Mais deux situations se viennent à l'esprit où je passerais à la version de la carte:

  • Si des instances typiques ne remplissent qu'une petite partie des champs, la solution de la carte peut être plus efficace de la mémoire. Mais en ce moment, c'est une optimisation prématurée, cela ne devrait donc pas être fait initialement, seulement après avoir trouvé un problème de consommation de mémoire, profilant et identifier votre classe comme l'origine de la faim de la mémoire.

  • Si vous avez besoin de getters génériques et de setters avec la clé souhaitée sous forme de paramètre, une carte supporte ce qui est tout naturellement naturellement, alors que le POJO a besoin d'une réflexion ou d'une longue instruction de commutation.

2
Ralf Kleberhoff

Utiliser un pojo. Pour la sérialisation, vous pouvez utiliser différents DTO que le mappeur pilotera ensuite de manière appropriée.

L'avantage est que vous pouvez ce dto ~

class DataView1DTO {
  private alpha;
  // getters / setters
}

class DataView2DTO {
  private alpha;
  private charlie;
  // getters / setters
}

Vous pouvez ensuite utiliser l'ObjectMapper pour transformer un objet "Data" en DataView1DTO ou DataView2DTo, tout comme ça.

Data myData // ...
DataView1DTO dto = myModelMapper.writeValue(myData, DataView1DTO.class);
// or...
DataView2DTO dto = myModelMapper.writeValue(myData, DataView2DTO.class)

puis le convertir en Json comme celui-ci

String dtoJson = myObjectMapper.writeValueAsString(dto);

Un exemple plus approprié serait des données utilisateur telles que le mot de passe ou d'autres données sensibles que vous ne pouvez pas transférer. Ou cela pourrait dépendre des privilèges du destinataire, vous auriez donc besoin de différents types de "vues".

J'espère que vous obtenez ce que je veux dire.

0
Aphton