package com.zaxxer.hikari.json.util;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

import com.zaxxer.hikari.json.JsonProperty;

public final class Clazz
{
   private final Class<?> actualClass;
   private final Map<Integer, Phield> fields;

   public Clazz(Class<?> clazz)
   {
      this.actualClass = clazz;
      this.fields = new HashMap<>((int)(actualClass.getDeclaredFields().length * 1.3));
   }

   void parseFields()
   {
      for (Field field : actualClass.getDeclaredFields()) {
         if (!Modifier.isStatic(field.getModifiers())) {
            JsonProperty jsonProperty = field.getAnnotation(JsonProperty.class);
            boolean excluded = (jsonProperty != null && jsonProperty.exclude());

            Phield phield = new Phield(field, excluded);
            if (jsonProperty != null) {
               fields.put(jsonProperty.name().hashCode(), phield);
            }
            else {
               fields.put(field.getName().hashCode(), phield);
               fields.put(field.getName().toLowerCase().hashCode(), phield);
            }
         }
      }
   }

   public Class<?> getActualClass() {
      return actualClass;
   }

   public Phield getPhield(final int hashCode) {
      return fields.get(hashCode);
   }

   @Override
   public String toString()
   {
      return "Clazz [" + actualClass.getCanonicalName() + "]";
   }

   public Object newInstance() throws InstantiationException, IllegalAccessException
   {
      return actualClass.newInstance();
   }
}

@@ -119,37 +119,14 @@
 til.
-HashMap;%0Aimport java.util.Map
+Arrays
 ;%0A%0Ai
@@ -235,16 +235,17 @@
 lClass;%0A
+%0A
    priva
@@ -256,37 +256,25 @@
 inal
- Map%3CInteger,
  Phield
-%3E
+%5B%5D
  fields;
 %0A%0A  
@@ -269,16 +269,88 @@
  fields;
+%0A   private final int%5B%5D fieldHashes;%0A   private final int%5B%5D quickLookup;
 %0A%0A   pub
@@ -416,94 +416,290 @@
 zz;%0A
+%0A
       
-this.fields = new HashMap%3C%3E((int)(actualClass.getDeclaredFields().length * 1.3))
+int fieldCount = 0;%0A      for (Field field : actualClass.getDeclaredFields()) %7B%0A         fieldCount += (Modifier.isStatic(field.getModifiers()) ? 0 : 1); %0A      %7D%0A%0A      fields = new Phield%5BfieldCount%5D;%0A      fieldHashes = new int%5BfieldCount%5D;%0A      quickLookup = new int%5B32%5D
 ;%0A  
@@ -725,24 +725,43 @@
 elds()%0A   %7B%0A
+      int ndx = 0;%0A
       for (F
@@ -962,24 +962,16 @@
     
-boolean excluded
+int hash
  = (
@@ -995,10 +995,9 @@
 ull 
-&&
+?
  jso
@@ -1010,21 +1010,57 @@
 rty.
-exclu
+name().hashCode() : field.getName().hashCo
 de());%0A
-%0A
     
@@ -1071,69 +1071,246 @@
     
-Ph
+f
 ield
- phield = new Ph
+Hashes%5Bndx%5D = hash;%0A            ndx++;%0A         %7D%0A      %7D%0A%0A      Arrays.sort(fieldHashes);%0A      for (F
 ield
-(
+ 
 field
-, excluded);%0A            if (
+ : actualClass.getDeclaredFields()) %7B%0A         if (!Modifier.isStatic(field.getModifiers())) %7B%0A            JsonProperty 
 json
@@ -1322,441 +1322,1171 @@
 rty 
-!
 = 
-null) %7B%0A               fields.put(jsonProperty.name().hashCode(), phield);%0A            %7D%0A            else %7B%0A               fields.put(field.getName().hashCode(), phield);%0A               fields.put(field.getName().toLowerCase().hashCode(), phield);%0A            %7D%0A         %7D%0A      %7D%0A   %7D%0A%0A   public Class%3C?%3E getActualClass() %7B%0A      return actualClass;%0A   %7D%0A%0A   public Phield getPhield(final int hashCode) %7B%0A      return fields.get(
+field.getAnnotation(JsonProperty.class);%0A            int hash = (jsonProperty != null ? jsonProperty.name().hashCode() : field.getName().hashCode());%0A            boolean excluded = (jsonProperty != null && jsonProperty.exclude());%0A%0A            Phield phield = new Phield(field, excluded);%0A%0A            // Hash slot%0A            int slot = (hash & quickLookup.length - 1);%0A            for (int i = 0; i %3C fieldHashes.length; i++) %7B%0A%0A               if (fieldHashes%5Bi%5D == hash) %7B%0A                  fields%5Bi%5D = phield;%0A                  quickLookup%5Bslot%5D = i + 1;%0A                  break;%0A               %7D%0A            %7D%0A         %7D%0A      %7D%0A   %7D%0A%0A   public Class%3C?%3E getActualClass() %7B%0A      return actualClass;%0A   %7D%0A%0A   public Phield getPhield(final int hashCode) %7B%0A      final int ndx = quickLookup%5B(hashCode & quickLookup.length - 1)%5D - 1; // Hash slot lookup%0A      if (ndx != -1 && fieldHashes%5Bndx%5D == hashCode) %7B%0A         return fields%5Bndx%5D;%0A      %7D%0A%0A      for (int i = 0; i %3C fieldHashes.length; i++) %7B%0A         if (fieldHashes%5Bi%5D == hashCode) %7B%0A            return fields%5Bi%5D;%0A         %7D%0A      %7D%0A%0A      throw new RuntimeException(%22No method found for hashCode %22 + 
 hash

Replace HashMap with parallel arrays and a quick lookup index