code: public static void addHash(ByteBuffer buffer, long hash64)
    {
      final int hash1 = (int) hash64;
      final int hash2 = (int) (hash64 >>> 32);
  
      int firstHash = hash1 + hash2;
      // hashcode should be positive, flip all the bits if it's negative
      if (firstHash < 0) {
        firstHash = ~firstHash;
      }
  
      ByteBuffer view = buffer.duplicate().order(ByteOrder.BIG_ENDIAN);
      int startPosition = view.position();
      int numHashFuncs = view.get(startPosition);
      int totalBlockCount = view.getInt(startPosition + 1) / DEFAULT_BLOCK_SIZE;
      // first hash is used to locate start of the block (blockBaseOffset)
      // subsequent K hashes are used to generate K bits within a block of words
      final int blockIdx = firstHash % totalBlockCount;
      final int blockBaseOffset = blockIdx << DEFAULT_BLOCK_SIZE_BITS;
      for (int i = 1; i <= numHashFuncs; i++) {
        int combinedHash = hash1 + ((i + 1) * hash2);
        // hashcode should be positive, flip all the bits if it's negative
        if (combinedHash < 0) {
          combinedHash = ~combinedHash;
        }
        // LSB 3 bits is used to locate offset within the block
        final int absOffset = blockBaseOffset + (combinedHash & DEFAULT_BLOCK_OFFSET_MASK);
        // Next 6 bits are used to locate offset within a long/word
        final int bitPos = (combinedHash >>> DEFAULT_BLOCK_SIZE_BITS) & DEFAULT_BIT_OFFSET_MASK;
  
        final int bufPos = startPosition + START_OF_SERIALIZED_LONGS + (absOffset * Long.BYTES);
        view.putLong(bufPos, view.getLong(bufPos) | (1L << bitPos));
      }
    }
docs: ByteBuffer based copy of {@link BloomKFilter#addHash(long)} that adds a value to the ByteBuffer in place.