Je suis curieux de savoir ce que les gens ici pensent d'utiliser
org.apache.commons.lang.builder
EqualsBuilder
/ HashCodeBuilder
pour implémenter le equals
/ hashCode
? Serait-ce une meilleure pratique que d'écrire la vôtre? Fonctionne-t-il bien avec Hibernate? Quelle est ton opinion?
155
reflectionEquals
etreflectionHashcode
; la performance est un tueur absolu.Réponses:
Les constructeurs commons / lang sont excellents et je les utilise depuis des années sans surcharge de performance notable (avec et sans mise en veille prolongée). Mais comme l'écrit Alain, la manière Goyave est encore plus agréable:
Voici un exemple de Bean:
Voici equals () et hashCode () implémentés avec Commons / Lang:
et ici avec Java 7 ou supérieur (inspiré de Guava):
Remarque: ce code faisait à l'origine référence à Guava, mais comme les commentaires l'ont souligné, cette fonctionnalité a depuis été introduite dans le JDK, donc Guava n'est plus nécessaire.
Comme vous pouvez le voir, la version Guava / JDK est plus courte et évite les objets auxiliaires superflus. En cas d'égalité, cela permet même de court-circuiter l'évaluation si un
Object.equals()
appel antérieur retourne false (pour être juste: commons / lang a uneObjectUtils.equals(obj1, obj2)
méthode avec une sémantique identique qui pourrait être utilisée au lieu deEqualsBuilder
permettre un court-circuit comme ci-dessus).Donc: oui, les communes constructeurs lang sont très préférables aux construits manuellement
equals()
ethashCode()
méthodes (ou ces monstres terribles Eclipse va générer pour vous), mais les versions Java 7+ / Goyave sont encore mieux.Et une note sur Hibernate:
soyez prudent lorsque vous utilisez des collections différées dans vos implémentations equals (), hashCode () et toString (). Cela échouera lamentablement si vous n'avez pas de session ouverte.
Remarque (environ égal à ()):
a) dans les deux versions de equals () ci-dessus, vous pouvez également utiliser l'un de ces raccourcis ou les deux:
b) en fonction de votre interprétation du contrat equals (), vous pouvez également changer la (les) ligne (s)
à
Si vous utilisez la deuxième version, vous souhaiterez probablement également appeler
super(equals())
votreequals()
méthode. Les opinions divergent ici, le sujet est discuté dans cette question:(même si c'est à peu près
hashCode()
, la même chose s'applique àequals()
)Note (inspirée du commentaire de kayahr )
Objects.hashCode(..)
(tout comme le sous-jacentArrays.hashCode(...)
) pourrait mal fonctionner si vous avez de nombreux champs primitifs. Dans de tels cas,EqualsBuilder
peut en fait être la meilleure solution.la source
equals
. Guava convertit toutes les valeurs en objets, commons-lang ne crée qu'un seul nouvel objet.Folks, réveillez-vous! Depuis Java 7, il existe des méthodes d'assistance pour equals et hashCode dans la bibliothèque standard. Leur utilisation est tout à fait équivalente à l'utilisation des méthodes Guava.
la source
Si vous ne voulez pas dépendre d'une bibliothèque tierce (peut-être que vous exécutez un appareil avec des ressources limitées) et que vous ne voulez même pas taper vos propres méthodes, vous pouvez également laisser l'EDI faire le travail, par exemple dans l'utilisation d'éclipse
Vous obtiendrez un code «natif» que vous pourrez configurer à votre guise et que vous devrez prendre en charge lors des modifications.
Exemple (éclipse Juno):
la source
equals
. Si vous ne voulez pas dépendre d'une bibliothèque tierce, écrivez la méthode en une ligne commeObjects.equal
vous. Même lorsqu'il n'est utilisé qu'une ou deux fois, le code est bien meilleur!equals
/hashCode
méthodes d'une ligne ???EqualsBuilder et HashCodeBuilder ont deux aspects principaux qui sont différents du code écrit manuellement:
EqualsBuilder et HashCodeBuilder facilitent la comparaison des champs qui pourraient être nuls. Avec le code écrit manuellement, cela crée beaucoup de passe-partout.
L'EqualsBuilder créera d'autre part une instance par appel de méthode equals. Si vos méthodes égales sont souvent appelées, cela créera de nombreuses instances.
Pour Hibernate, l'implémentation equals et hashCode ne font aucune différence. Ils ne sont qu'un détail de mise en œuvre. Pour presque tous les objets de domaine chargés avec hibernate, la surcharge d'exécution (même sans analyse d'échappement) du générateur peut être ignorée . Les frais généraux liés à la base de données et aux communications seront importants.
Comme skaffman l'a mentionné, la version de réflexion ne peut pas être utilisée dans le code de production. La réflexion sera trop lente et la "mise en œuvre" ne sera pas correcte pour toutes les classes sauf les plus simples. La prise en compte de tous les membres est également dangereuse car les membres nouvellement introduits modifient le comportement de la méthode égale. La version de réflexion peut être utile dans le code de test.
la source
Si vous ne rédigez pas le vôtre, il y a aussi la possibilité d'utiliser google guava (anciennement google collections)
la source
Si vous vous occupez uniquement du bean entité où id est une clé primaire, vous pouvez simplifier.
la source
À mon avis, cela ne fonctionne pas bien avec Hibernate, en particulier les exemples de la réponse comparant la longueur, le nom et les enfants d'une entité. Hibernate conseille d'utiliser la clé métier à utiliser dans equals () et hashCode (), et ils ont leurs raisons. Si vous utilisez le générateur auto equals () et hashCode () sur votre clé métier, ce n'est pas grave, seuls les problèmes de performances doivent être pris en compte comme mentionné précédemment. Mais les gens utilisent généralement toutes les propriétés, ce qui est très faux. Par exemple, je travaille actuellement sur un projet où les entités sont écrites en utilisant Pojomatic avec @AutoProperty, ce que je considère comme un très mauvais modèle.
Leurs deux principaux scénarios d'utilisation de hashCode () et equals () sont:
Supposons donc que notre entité ressemble à ceci:
Les deux sont la même entité pour Hibernate, qui ont été extraites d'une session à un moment donné (leur identifiant et leur classe / table sont égaux). Mais quand nous implémentons auto equals () un hashCode () sur tous les accessoires, qu'avons-nous?
Donc, pour 99% du projet que je fais, nous utilisons l'implémentation suivante de equals () et hashCode () écrite une fois dans la classe d'entité de base, ce qui est cohérent avec les concepts Hibernate:
Pour l'entité transitoire, je fais la même chose que Hibernate fera lors de l'étape de persistance, c'est-à-dire. J'utilise la correspondance d'instance. Pour les objets persistants, je compare la clé unique, qui est la table / id (je n'utilise jamais de clés composites).
la source
Juste au cas où d'autres trouveraient cela utile, j'ai mis au point cette classe Helper pour le calcul de code de hachage qui évite la surcharge de création d'objets supplémentaire mentionnée ci-dessus (en fait, la surcharge de la méthode Objects.hash () est encore plus grande lorsque vous avez héritage car il créera un nouveau tableau à chaque niveau!).
Exemple d'utilisation:
L'assistant HashCode:
J'ai pensé que 10 est le nombre maximum raisonnable de propriétés dans un modèle de domaine, si vous en avez plus, vous devriez penser à refactoriser et à introduire plus de classes au lieu de maintenir un tas de chaînes et de primitives.
Les inconvénients sont: ce n'est pas utile si vous avez principalement des primitives et / ou des tableaux dont vous avez besoin pour hacher profondément. (Normalement, c'est le cas lorsque vous devez gérer des objets plats (transfert) qui sont hors de votre contrôle).
la source