Lombok: Problema con hashCode () en el atributo nulo cuando se usa en una estructura basada en hash

Creado en 19 jul. 2019  ·  3Comentarios  ·  Fuente: projectlombok/lombok

La anotación @EqualsAndHashCode que usa un atributo largo como pk puede causar un comportamiento inesperado cuando se usa con una estructura basada en hash (como HashSet).

p.ej.:

<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());
    }
}

Entonces, cuando la instancia con pk = null y otra con pk = 43, devolverá el mismo código hash y puede considerarse igual en la estructura basada en hash, que no lo son.

Y en el caso de usar OmniFaces ListConverter que usa toString tenemos el mismo problema.

Tal vez devuelva un código hash de la instancia del objeto en lugar de una constante codificada

¿Ya tomó este escenario o conoce alguna forma de solucionar esta situación?

Información de la versión

  • Lombok => 1.18.8
  • Plataforma => Windows 10 JDK 11.0.4 IntelliJ

Comentario más útil

43 es probablemente tan bueno como cualquier otro número, y mejor que -1, 0 y 1. Hacerlo configurable agrega carga de mantenimiento por un valor agregado muy bajo.

Usar el código hash de identidad para nulo rompería el contrato de igualdad.

Todos 3 comentarios

Entonces, cuando la instancia con pk = null y otra con pk = 43, devolverá el mismo código hash

esto no importa Además, siempre habrá colisiones de hash, sin importar lo que elijas.

Tenga en cuenta que Arrays.hashCode , String.hashCode y muchos otros producen toneladas de colisiones, bastante innecesariamente.

Tal vez devuelva un código hash de la instancia del objeto en lugar de una constante codificada

En mi código escrito manualmente, afirmo que no se llama antes de que se asigne un id . Eso es sin duda extraño, pero también lo son todas las alternativas.

Sería posible crear un parámetro de anotación que pudiera indicar qué valor se debe usar cuando el PK es nulo, en este caso. Por defecto 43.

Esto le daría más control al desarrollador.

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

Entonces usará -1 en lugar de 43, para cualquier campo que sea nulo

43 es probablemente tan bueno como cualquier otro número, y mejor que -1, 0 y 1. Hacerlo configurable agrega carga de mantenimiento por un valor agregado muy bajo.

Usar el código hash de identidad para nulo rompería el contrato de igualdad.

¿Fue útil esta página
0 / 5 - 0 calificaciones