Tengo curiosidad por saber, ¿qué piensa la gente de usar
org.apache.commons.lang.builder
EqualsBuilder
/ HashCodeBuilder
para implementar el equals
/ hashCode
? ¿Sería una mejor práctica que escribir la tuya? ¿Juega bien con Hibernate? ¿Cual es tu opinion?
155
reflectionEquals
yreflectionHashcode
; El rendimiento es un asesino absoluto.Respuestas:
Los creadores de commons / lang son geniales y los he estado usando durante años sin sobrecarga de rendimiento notable (con y sin hibernación). Pero como Alain escribe, la forma de la guayaba es aún mejor:
Aquí hay una muestra de Bean:
Aquí está equals () y hashCode () implementado con Commons / Lang:
y aquí con Java 7 o superior (inspirado en Guava):
Nota: este código originalmente hacía referencia a Guava, pero como los comentarios han señalado, esta funcionalidad se ha introducido en el JDK, por lo que Guava ya no es necesaria.
Como puede ver, la versión Guava / JDK es más corta y evita objetos auxiliares superfluos. En caso de igual, incluso permite un cortocircuito en la evaluación si una
Object.equals()
llamada anterior devuelve falso (para ser justos: commons / lang tiene unObjectUtils.equals(obj1, obj2)
método con semántica idéntica que podría usarse en lugar deEqualsBuilder
permitir un cortocircuito como se indicó anteriormente).Entonces: sí, los constructores de lang comunes son muy preferibles a los métodos
equals()
yhashCode()
métodos construidos manualmente (o esos monstruos horribles que Eclipse generará para usted), pero las versiones de Java 7+ / Guava son aún mejores.Y una nota sobre Hibernate:
tenga cuidado con el uso de colecciones diferidas en sus implementaciones equals (), hashCode () y toString (). Eso fallará miserablemente si no tiene una sesión abierta.
Nota (sobre equals ()):
a) en ambas versiones de equals () anteriores, es posible que desee utilizar uno o ambos de estos atajos también:
b) dependiendo de su interpretación del contrato equals (), también puede cambiar la (s) línea (s)
a
Si usa la segunda versión, probablemente también desee llamar
super(equals())
dentro de suequals()
método. Las opiniones difieren aquí, el tema se discute en esta pregunta:(aunque se trata
hashCode()
, lo mismo se aplica aequals()
)Nota (inspirada en el comentario de kayahr )
Objects.hashCode(..)
(al igual que el subyacenteArrays.hashCode(...)
) podría funcionar mal si tiene muchos campos primitivos. En tales casos, enEqualsBuilder
realidad puede ser la mejor solución.fuente
equals
. Guava convierte todos los valores en objetos, commons-lang solo crea un único objeto nuevo.Amigos, despierten! Desde Java 7 hay métodos auxiliares para equals y hashCode en la biblioteca estándar. Su uso es totalmente equivalente al uso de los métodos de guayaba.
fuente
Si no desea depender de una biblioteca de terceros (tal vez está ejecutando un dispositivo con recursos limitados) e incluso no desea escribir sus propios métodos, también puede dejar que el IDE haga el trabajo, por ejemplo, en uso de eclipse
Obtendrá un código 'nativo' que puede configurar a su gusto y que debe admitir en los cambios.
Ejemplo (eclipse Juno):
fuente
equals
. Si no desea depender de una biblioteca de terceros, escriba el método de una línea comoObjects.equal
usted. ¡Incluso cuando se usa solo una o dos veces, mejora el código!equals
/hashCode
métodos de una línea ???EqualsBuilder y HashCodeBuilder tienen dos aspectos principales que son diferentes del código escrito manualmente:
EqualsBuilder y HashCodeBuilder facilitan la comparación de campos que podrían ser nulos. Con el código escrito manualmente, esto crea una gran cantidad de repeticiones.
El EqualsBuilder, por otro lado, creará una instancia por llamada al método igual. Si sus métodos de igualdad son llamados a menudo, esto creará muchas instancias.
Para Hibernate, la implementación de igual y hashCode no hace ninguna diferencia. Son solo un detalle de implementación. Para casi todos los objetos de dominio cargados con hibernación, se puede ignorar la sobrecarga de tiempo de ejecución (incluso sin análisis de escape) del generador . La sobrecarga de la base de datos y la comunicación será significativa.
Como skaffman mencionó, la versión de reflexión no se puede usar en el código de producción. La reflexión será lenta y la "implementación" no será correcta para todas las clases excepto las más simples. Tener en cuenta a todos los miembros también es peligroso ya que los miembros recién introducidos cambian el comportamiento del método igual. La versión de reflexión puede ser útil en el código de prueba.
fuente
Si no escribe el suyo, también existe la posibilidad de usar google guava (anteriormente colecciones de google)
fuente
Si solo está tratando con el bean de entidad donde id es una clave principal, puede simplificar.
fuente
En mi opinión, no funciona bien con Hibernate, especialmente los ejemplos de la respuesta que comparan longitud, nombre e hijos para alguna entidad. Hibernate aconseja utilizar la clave comercial para ser utilizada en equals () y hashCode (), y tienen sus razones. Si usa el generador auto equals () y hashCode () en su clave comercial, está bien, solo los problemas de rendimiento deben considerarse como se mencionó anteriormente. Pero la gente generalmente usa todas las propiedades de lo que es IMO muy mal. Por ejemplo, actualmente estoy trabajando en un proyecto donde las entidades se escriben usando Pojomatic con @AutoProperty, lo que considero un patrón realmente malo.
Sus dos escenarios principales para usar hashCode () y equals () son:
Así que supongamos que nuestra entidad se ve así:
Ambos son la misma entidad para Hibernate, que se han obtenido de alguna sesión en algún momento (su id y clase / tabla son iguales). Pero cuando implementamos auto equals () a hashCode () en todos los accesorios, ¿qué tenemos?
Entonces, para el 99% del proyecto que realizo, utilizamos la siguiente implementación de equals () y hashCode () escritos una vez en la clase de entidad base, que es consistente con los conceptos de Hibernate:
Para la entidad transitoria, hago lo mismo que Hibernate hará en el paso de persistencia, es decir. Yo uso el partido de instancia. Para los objetos persistentes, comparo la clave única, que es la tabla / id (nunca uso claves compuestas).
fuente
Por si acaso, a otros les resultará útil, se me ocurrió esta clase de ayuda para el cálculo de código hash que evita la sobrecarga de creación de objetos adicionales mencionada anteriormente (de hecho, la sobrecarga del método Objects.hash () es aún mayor cuando tienes herencia ya que creará una nueva matriz en cada nivel!).
Ejemplo de uso:
El ayudante HashCode:
Me imaginé que 10 es el número máximo razonable de propiedades en un modelo de dominio, si tiene más, debería pensar en refactorizar e introducir más clases en lugar de mantener un montón de cadenas y primitivas.
Los inconvenientes son: no es útil si tiene principalmente primitivas y / o matrices que necesita analizar profundamente. (Normalmente este es el caso cuando tiene que lidiar con objetos planos (de transferencia) que están fuera de su control).
fuente