@Override
  public int hashCode() {
    int hash = _hash;
    if (hash == 1 && _bytes.length > 0) {
      int i = 0;
      for (; i + 7 < _bytes.length; i += 8) {
        hash = -1807454463 * hash
            + 1742810335 * _bytes[i]
            + 887503681 * _bytes[i + 1]
            + 28629151 * _bytes[i + 2]
            + 923521 * _bytes[i + 3]
            + 29791 * _bytes[i + 4]
            + 961 * _bytes[i + 5]
            + 31 * _bytes[i + 6]
            + _bytes[i + 7];
      }
      for (; i < _bytes.length; i++) {
        hash = 31 * hash + _bytes[i];
      }
      _hash = hash;
    }
    return hash;
  }
@Test(description = "hash code may have been used for partitioning so must be stable")
  public void testHashCode() {
    // ensure to test below 8
    byte[] bytes = new byte[ThreadLocalRandom.current().nextInt(8)];
    ThreadLocalRandom.current().nextBytes(bytes);
    assertEquals(Arrays.hashCode(bytes), new ByteArray(bytes).hashCode());
    for (int i = 0; i < 10_000; i++) {
      bytes = new byte[ThreadLocalRandom.current().nextInt(2048)];
      ThreadLocalRandom.current().nextBytes(bytes);
      assertEquals(Arrays.hashCode(bytes), new ByteArray(bytes).hashCode());
    }
  }