/** {@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 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 boolean forEachValue(TCharProcedure procedure) {
   TByteOffheapArray states = _states;
   TCharOffheapArray values = _values;
   for (int i = capacity(); i-- > 0; ) {
     if (states.get(i) == FULL && !procedure.execute(values.get(i))) {
       return false;
     }
   }
   return true;
 }
 /** {@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 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 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;
    }
  /** {@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 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();
  }