docs: private InternalCacheEntry<WrappedBytes, WrappedBytes> performRemove(long bucketHeadAddress, long actualAddress,
           WrappedBytes key, WrappedBytes value, boolean requireReturn) {
        long prevAddress = 0;
        // We only use the head pointer for the first iteration
        long address = bucketHeadAddress;
        InternalCacheEntry<WrappedBytes, WrappedBytes> ice = null;
  
        while (address != 0) {
           long nextAddress = offHeapEntryFactory.getNext(address);
           boolean removeThisAddress;
           // If the actualAddress was not known, check key equality otherwise just compare with the address
           removeThisAddress = actualAddress == 0 ? offHeapEntryFactory.equalsKey(address, key) : actualAddress == address;
           if (removeThisAddress) {
              if (value != null) {
                 ice = offHeapEntryFactory.fromMemory(address);
                 // If value doesn't match and was provided then don't remove it
                 if (!value.equalsWrappedBytes(ice.getValue())) {
                    ice = null;
                    break;
                 }
              }
              if (requireReturn && ice == null) {
                 ice = offHeapEntryFactory.fromMemory(address);
              }
              entryRemoved(address);
              if (prevAddress != 0) {
                 offHeapEntryFactory.setNext(prevAddress, nextAddress);
              } else {
                 memoryLookup.putMemoryAddress(key, nextAddress);
              }
              size.decrementAndGet();
              break;
           }
           prevAddress = address;
           address = nextAddress;
        }
        return ice;
     }