Lombok: Problème avec hashCode() sur l'attribut null lorsqu'il est utilisé sur une structure basée sur le hachage

Créé le 19 juil. 2019  ·  3Commentaires  ·  Source: projectlombok/lombok

L'annotation @EqualsAndHashCode qui utilise l'attribut Long tel que pk peut provoquer un comportement inattendu lorsqu'elle est utilisée avec une structure basée sur le hachage (comme HashSet).

par exemple.:

<strong i="9">@Entity</strong>
@EqualsAndHashCode(of = "pk")
class Foo {

    <strong i="10">@Id</strong>
    private Long pk;

    private LocalDate createdAt;

}
<strong i="13">@Entity</strong>
class Foo {

    <strong i="14">@Id</strong>
    private Long pk;

    private LocalDate createdAt;

    public int hashCode() {
        int PRIME = true;
        int result = 1;
        Object $pk = this.getPk();
        int result = result * 59 + ($pk == null ? 43 : $pk.hashCode());
        return result;
    }

    public String toString() {
        return getClass().getName() + "@" + Integer.toHexString(hashCode());
    }
}

Ainsi, lorsque l'instance avec pk = null et autre avec pk = 43, elle renverra le même code de hachage et il peut être considéré comme identique sur la structure basée sur le hachage, ce qu'ils ne sont pas.

Et dans le cas d'utilisation d'OmniFaces ListConverter qui utilise toString nous avons le même problème.

Peut-être renvoyer un hashcode de l'instance d'objet plutôt qu'une constante codée en dur

Avez-vous déjà pris ce scénario, ou connaissez-vous un moyen de contourner cette situation ? !

Informations sur les versions

  • Lombok => 1.18.8
  • Plate-forme => Windows 10 JDK 11.0.4 IntelliJ

Commentaire le plus utile

43 est probablement aussi bon que n'importe quel autre nombre, et meilleur que -1, 0 et 1. Le rendre configurable ajoute une charge de maintenance pour une très faible valeur ajoutée.

L'utilisation du hashcode Identity pour null romprait le contrat d'égalité.

Tous les 3 commentaires

Ainsi, lorsque l'instance avec pk = null et autre avec pk = 43, elle renverra le même code de hachage

Cela n'a pas d'importance. De plus, il y aura toujours des collisions de hachage, peu importe ce que vous choisissez.

Notez que Arrays.hashCode , String.hashCode et bien d'autres produisent des tonnes de collisions, plutôt inutilement.

Peut-être renvoyer un hashcode de l'instance d'objet plutôt qu'une constante codée en dur

Dans mon code écrit manuellement, j'affirme qu'il n'est pas appelé avant qu'un id ne soit attribué. C'est sûrement étrange, mais toutes les alternatives le sont aussi.

Il serait possible de créer un paramètre d'annotation qui pourrait dire quelle valeur doit être utilisée lorsque le PK est nul, dans ce cas. Par défaut 43.

Cela donnerait plus de contrôle au développeur.

@EqualsAndHashCode(of = "pk", ifAnyNull = -1)

Il utilisera donc -1 au lieu de 43, pour tout champ nul

43 est probablement aussi bon que n'importe quel autre nombre, et meilleur que -1, 0 et 1. Le rendre configurable ajoute une charge de maintenance pour une très faible valeur ajoutée.

L'utilisation du hashcode Identity pour null romprait le contrat d'égalité.

Cette page vous a été utile?
0 / 5 - 0 notes