From 30be95de3223238dd28e2ed76598d1fb95de32c2 Mon Sep 17 00:00:00 2001 From: Ladislav Thon Date: Thu, 21 Sep 2023 08:45:11 +0200 Subject: [PATCH] improve AnnotationInstance.hashCode() The `AnnotationInstance.equals()` method considers two annotations that are basically the same as distinct if they don't have the same `target`. However, the `AnnotationInstance.hashCode()` method does not take the `target` into account at all, which leads to hash table collisions. This commit uses the `AnnotationTarget` information to spread out the `AnnotationInstance` hash code to make collisions less likely. --- .../org/jboss/jandex/AnnotationInstance.java | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java index 57f95ca7..7961f3d2 100644 --- a/core/src/main/java/org/jboss/jandex/AnnotationInstance.java +++ b/core/src/main/java/org/jboss/jandex/AnnotationInstance.java @@ -432,8 +432,7 @@ public String toString() { /** * Returns whether this annotation instance is equal to another instance. * Two annotation instances are equal if their names and values of their members are equal, - * and they share the exact same {@code AnnotationTarget} instance. The latter restriction - * may be softened in future versions. + * and they share the exact same {@code AnnotationTarget} instance. * * @param o the annotation instance to compare to * @return {@code true} if equal, {@code false} if not @@ -463,6 +462,36 @@ public int hashCode() { int result = name.hashCode(); result = 31 * result + Arrays.hashCode(values); + if (target != null) { + switch (target.kind()) { + case CLASS: + result = 31 * result + target.asClass().name().hashCode(); + break; + case METHOD: + result = 31 * result + target.asMethod().declaringClass().name().hashCode(); + result = 31 * result + target.asMethod().name().hashCode(); + break; + case FIELD: + result = 31 * result + target.asField().declaringClass().name().hashCode(); + result = 31 * result + target.asField().name().hashCode(); + break; + case METHOD_PARAMETER: + result = 31 * result + target.asMethodParameter().method().declaringClass().name().hashCode(); + result = 31 * result + target.asMethodParameter().method().name().hashCode(); + result = 31 * result + target.asMethodParameter().position(); + break; + case RECORD_COMPONENT: + result = 31 * result + target.asRecordComponent().declaringClass().name().hashCode(); + result = 31 * result + target.asRecordComponent().name().hashCode(); + break; + case TYPE: + if (target.asType().target() != null) { + result = 31 * result + target.asType().target().name().hashCode(); + } + break; + } + } + return result; }