public static int writableArrayHashCode(Object[] keys) {
    if (keys == null) return 0;
    int hashcode = 1;
    for (Object element : keys) {
      hashcode = 31 * hashcode;
      if (element == null) {
        // nothing
      } else if (element instanceof LazyDouble) {
        long v = Double.doubleToLongBits(((LazyDouble) element).getWritableObject().get());
        hashcode = hashcode + (int) (v ^ (v >>> 32));
      } else if (element instanceof DoubleWritable) {
        long v = Double.doubleToLongBits(((DoubleWritable) element).get());
        hashcode = hashcode + (int) (v ^ (v >>> 32));
      } else if (element instanceof Object[]) {
        // use deep hashcode for arrays
        hashcode = hashcode + Arrays.deepHashCode((Object[]) element);
      } else {
        hashcode = hashcode + element.hashCode();
      }
    }
    return hashcode;
  }
Calculates the hash code for array of Objects that contains writables. This is used
to work around the buggy Hadoop DoubleWritable hashCode implementation. This should
only be used for process-local hash codes; don't replace stored hash codes like bucketing.
serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java