/** {@inheritDoc} */
 @Override
 public boolean forEachEntry(TCharCharProcedure procedure) {
   TByteOffheapArray states = _states;
   TCharOffheapArray keys = _set;
   TCharOffheapArray values = _values;
   for (int i = capacity(); i-- > 0; ) {
     if (states.get(i) == FULL && !procedure.execute(keys.get(i), values.get(i))) {
       return false;
     }
   }
   return true;
 }
 /** {@inheritDoc} */
 @Override
 public boolean equals(Object other) {
   if (!(other instanceof TCharCharMap)) {
     return false;
   }
   TCharCharMap that = (TCharCharMap) other;
   if (that.size() != this.size()) {
     return false;
   }
   TCharOffheapArray values = _values;
   TByteOffheapArray states = _states;
   char this_no_entry_value = getNoEntryValue();
   char that_no_entry_value = that.getNoEntryValue();
   for (int i = capacity(); i-- > 0; ) {
     if (states.get(i) == FULL) {
       char key = _set.get(i);
       char that_value = that.get(key);
       char this_value = values.get(i);
       if ((this_value != that_value)
           && (this_value != this_no_entry_value)
           && (that_value != that_no_entry_value)) {
         return false;
       }
     }
   }
   return true;
 }
 /** {@inheritDoc} */
 @Override
 public char remove(char key) {
   char prev = no_entry_value;
   int index = index(key);
   if (index >= 0) {
     prev = _values.get(index);
     removeAt(index); // clear key,state; adjust size
   }
   return prev;
 }
 /** {@inheritDoc} */
 @Override
 public void transformValues(TCharFunction function) {
   TByteOffheapArray states = _states;
   TCharOffheapArray values = _values;
   for (int i = capacity(); i-- > 0; ) {
     if (states.get(i) == FULL) {
       values.put(i, function.execute(values.get(i)));
     }
   }
 }
 /** {@inheritDoc} */
 @Override
 public int hashCode() {
   int hashcode = 0;
   TByteOffheapArray states = _states;
   for (int i = capacity(); i-- > 0; ) {
     if (states.get(i) == FULL) {
       hashcode += HashFunctions.hash(_set.get(i)) ^ HashFunctions.hash(_values.get(i));
     }
   }
   return hashcode;
 }
 /** {@inheritDoc} */
 @Override
 public boolean adjustValue(char key, char amount) {
   int index = index(key);
   if (index < 0) {
     return false;
   } else {
     char val = _values.get(index);
     _values.put(index, (char) (val + amount));
     return true;
   }
 }
  /** {@inheritDoc} */
  @Override
  public boolean containsValue(char val) {
    TByteOffheapArray states = _states;
    TCharOffheapArray vals = _values;

    for (int i = capacity(); i-- > 0; ) {
      if (states.get(i) == FULL && val == vals.get(i)) {
        return true;
      }
    }
    return false;
  }
  /** {@inheritDoc} */
  @Override
  public char[] values() {
    char[] vals = new char[size()];
    TCharOffheapArray v = _values;
    TByteOffheapArray states = _states;

    for (int i = capacity(), j = 0; i-- > 0; ) {
      if (states.get(i) == FULL) {
        vals[j++] = v.get(i);
      }
    }
    return vals;
  }
  /** {@inheritDoc} */
  @Override
  public char[] keys() {
    char[] keys = new char[size()];
    TCharOffheapArray k = _set;
    TByteOffheapArray states = _states;

    for (int i = capacity(), j = 0; i-- > 0; ) {
      if (states.get(i) == FULL) {
        keys[j++] = k.get(i);
      }
    }
    return keys;
  }
  /** {@inheritDoc} */
  @Override
  public boolean retainEntries(TCharCharProcedure procedure) {
    boolean modified = false;
    TByteOffheapArray states = _states;
    TCharOffheapArray keys = _set;
    TCharOffheapArray values = _values;

    // Temporarily disable compaction. This is a fix for bug #1738760
    tempDisableAutoCompaction();
    try {
      for (int i = capacity(); i-- > 0; ) {
        if (states.get(i) == FULL && !procedure.execute(keys.get(i), values.get(i))) {
          removeAt(i);
          modified = true;
        }
      }
    } finally {
      reenableAutoCompaction(true);
    }

    return modified;
  }
  /** {@inheritDoc} */
  @Override
  protected void rehash(int newCapacity) {
    int oldCapacity = capacity();

    TCharOffheapArray oldKeys = _set;
    TCharOffheapArray oldVals = _values;
    TByteOffheapArray oldStates = _states;

    _set = new TCharOffheapArray(newCapacity);
    _values = new TCharOffheapArray(newCapacity);
    _states = new TByteOffheapArray(newCapacity);

    for (int i = oldCapacity; i-- > 0; ) {
      if (oldStates.get(i) == FULL) {
        char o = oldKeys.get(i);
        int index = insertKey(o);
        _values.put(index, oldVals.get(i));
      }
    }
    oldKeys.free();
    oldVals.free();
    oldStates.free();
  }
    /** {@inheritDoc} */
    @Override
    public boolean remove(char entry) {
      TCharOffheapArray values = _values;
      TByteOffheapArray states = _states;

      for (int i = capacity(); i-- > 0; ) {
        byte state = states.get(i);
        if ((state != FREE && state != REMOVED) && entry == values.get(i)) {
          removeAt(i);
          return true;
        }
      }
      return false;
    }
    /** {@inheritDoc} */
    @Override
    public boolean retainAll(char[] array) {
      boolean changed = false;
      Arrays.sort(array);
      TCharOffheapArray values = _values;
      TByteOffheapArray states = _states;

      for (int i = capacity(); i-- > 0; ) {
        if (states.get(i) == FULL && (Arrays.binarySearch(array, values.get(i)) < 0)) {
          removeAt(i);
          changed = true;
        }
      }
      return changed;
    }
  private char doPut(char key, char value, int index) {
    char previous = no_entry_value;
    boolean isNewMapping = true;
    if (index < 0) {
      index = -index - 1;
      previous = _values.get(index);
      isNewMapping = false;
    }
    _values.put(index, value);

    if (isNewMapping) {
      postInsertHook(consumeFreeSlot);
    }

    return previous;
  }
  /** {@inheritDoc} */
  @Override
  public char[] values(char[] array) {
    int size = size();
    if (array.length < size) {
      array = new char[size];
    }

    TCharOffheapArray v = _values;
    TByteOffheapArray states = _states;

    for (int i = capacity(), j = 0; i-- > 0; ) {
      if (states.get(i) == FULL) {
        array[j++] = v.get(i);
      }
    }
    return array;
  }
  /** {@inheritDoc} */
  @Override
  public void writeExternal(ObjectOutput out) throws IOException {
    // VERSION
    out.writeByte(0);

    // SUPER
    super.writeExternal(out);

    // NUMBER OF ENTRIES
    out.writeInt(_size);

    // ENTRIES
    for (int i = capacity(); i-- > 0; ) {
      if (_states.get(i) == FULL) {
        out.writeChar(_set.get(i));
        out.writeChar(_values.get(i));
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public char adjustOrPutValue(char key, char adjust_amount, char put_amount) {
    int index = insertKey(key);
    final boolean isNewMapping;
    final char newValue;
    if (index < 0) {
      index = -index - 1;
      newValue = (char) (_values.get(index) + adjust_amount);
      isNewMapping = false;
    } else {
      newValue = put_amount;
      isNewMapping = true;
    }

    _values.put(index, newValue);

    if (isNewMapping) {
      postInsertHook(consumeFreeSlot);
    }

    return newValue;
  }
 /** {@inheritDoc} */
 @Override
 public char putIfAbsent(char key, char value) {
   int index = insertKey(key);
   if (index < 0) return _values.get(-index - 1);
   return doPut(key, value, index);
 }
 /** {@inheritDoc} */
 @Override
 public char get(char key) {
   int index = index(key);
   return index < 0 ? no_entry_value : _values.get(index);
 }