/**
   * Returns an int to int hashmap that represent the sorted order of the values in <code>values
   * </code> through the keys in <code>validKeys</code>.
   *
   * @param validKeys Keys from this map that a sorted order for their values should be returned,
   *     sorted.
   * @param values Values mapped to items in <code>validKeys</code>, sorted.
   * @return VIntIntHashMap with valid keys from <code>validKeys</code> such that for each pair of
   *     keys (i,j) ley (x,y) be their maped values in the returned value. If (i<=j) then the value
   *     that is mapped x is smaller than or equal to the value that is mapped to y.
   */
  private VIntIntHashMap getSortedOrder(int[] validKeys, byte[] values) {

    // will hold the new order to be sorted according to.
    int[] newOrder = new int[validKeys.length];

    // flags associated with newOrder
    boolean[] ocuupiedIndices = new boolean[validKeys.length];

    byte currVal; // current value for which its place is searched

    // for each valid row validRows[i]
    for (int i = 0; i < validKeys.length; i++) {

      currVal = get(validKeys[i]);

      // finding the index of its mapped String
      int newKey = Arrays.binarySearch(values, currVal);

      // because binarySearch can return the same index for items that are
      // identical checking for this option too.
      if (ocuupiedIndices[newKey]) {
        newKey = getNewKey(currVal, values, newKey, ocuupiedIndices);
      }

      ocuupiedIndices[newKey] = true; // marking the flag

      // validRows[i] will be swapped with validRows[newRow] by reorderRows.
      newOrder[newKey] = validKeys[i];
    } // end of for

    // creating a map between the old order and the new order.
    return VHashService.getMappedOrder(validKeys, newOrder);
  } // end method getSortedOrder
  /**
   * Returns an int to int hash map with old row numbers mapped to new row numbers, which defines a
   * sorted order for this column
   *
   * @param validRows row numbers from which the sorted order is retrieved.
   */
  public VIntIntHashMap getNewOrder(int[] validRows) {

    Object[] sortedValues = getValuesInRange(validRows[0], validRows[validRows.length - 1]);

    Object[] rawValues = getValues(validRows);

    // will hold the new order, the returned value.
    int[] newOrder = new int[validRows.length];

    // a flag array. occupiedIndices[j] == true mean that the row number
    // stored at validRows[j] was already mapped to a value in tempMap
    boolean[] ocuupiedIndices = new boolean[validRows.length];

    // for each valid row validRows[i]
    for (int i = 0; i < validRows.length; i++) {

      // finding the index of its mapped Object in values

      int newRow = Arrays.binarySearch(sortedValues, rawValues[i]);

      // because binarySearch can return the same index for items that are identical
      // checking for this option too.
      if (ocuupiedIndices[newRow]) {

        // if newRow index was already used - finding an alternative index
        newRow = getNewRow(rawValues[i], sortedValues, newRow, ocuupiedIndices);

        // marking the associated flag as true
      }
      ocuupiedIndices[newRow] = true;

      newOrder[newRow] = validRows[i];
    } // end of for
    return VHashService.getMappedOrder(validRows, newOrder);
  }
  /**
   * Inserts <code>obj</code> to be mapped to key <code>key<code>. All values
   * mapped to keys <code>key</code> and on will be mapped to a key greater in
   * one.</code></code>
   *
   * @param obj Object to be inserted into the map.
   * @param key The insertion key
   */
  public void insertObject(Object obj, int key) {

    // moving all elements mapped to key through the maximal key
    // to be mapped to a key greater in 1.
    int max = VHashService.getMaxKey(this);
    int[] keysInRange = VHashService.getIndicesInRange(key, max, this);

    for (int i = keysInRange.length - 1; i >= 0; i--) {
      byte removed = remove(keysInRange[i]);
      put(keysInRange[i] + 1, removed);
    }

    // putting the new object in key.
    if (obj != null) {
      put(key, SparseByteColumn.toByte(obj));
    }
  }
  /**
   * Returns an int to int hashmap that represents a sorted order for the values of this map.
   *
   * <p>Such that for each pair of keys (i,j) ey (x,y) be their maped values in the returned value.
   * If (i<=j) then the value that is mapped x smaller than or equal to the value that is mapped to
   * y.
   *
   * @return Returns an int to int hashmap that represents a sorted order for the values of this
   *     map.
   */
  public VIntIntHashMap getSortedOrder() {

    int[] validKeys = VHashService.getIndices(this);

    byte[] values = getValues();
    Arrays.sort(values);

    return getSortedOrder(validKeys, values);
  }
  /**
   * Returns a subset of this map with values that are mapped to keys <code>
   * start</code> through <codE>start+len</code>.
   *
   * @param start Key number from which to start retrieving subset
   * @param len Number of consequetive keys to retrieve their values into the subset
   * @return VIntByteHashMap with values and keys from this map, such that keys' range is <code>
   *     start</code> through <code>start+len</code>
   */
  public VHashMap getSubset(int start, int len) {
    VIntByteHashMap retVal = new VIntByteHashMap(len);

    int[] validKeys = VHashService.getIndicesInRange(start, start + len - 1, this);

    for (int i = 0; i < validKeys.length; i++) {

      retVal.put(validKeys[i] - start, get(validKeys[i]));
    }

    return retVal;
  }
  /**
   * Returns an int to int hashmap that represents a sorted order for the values of this map in the
   * range <code>begin</code> through <code>
   * end</code>.
   *
   * @param begin Key number from which to start retrieving the new order
   * @param end Last key in the section from which to retrieve the new order.
   * @return A VIntIntHashMap with valid keys from the specified section such that for each pair of
   *     keys (i,j) ley (x,y) be their maped values. If (i<=j) then the value that is mapped x is
   *     smaller than or equal to the value that is mapped to y.
   */
  public VIntIntHashMap getSortedOrder(int begin, int end) {

    if (end < begin) {
      return new VIntIntHashMap(0);
    }

    // sorting the valid row numbers
    int[] validKeys = VHashService.getIndicesInRange(begin, end, this);

    // sorting the values
    byte[] values = getValuesInRange(begin, end);

    return getSortedOrder(validKeys, values);
  }
  /**
   * Returns the valid values in rows <codE>begin</code> through <codE>end</code>
   *
   * @param begin row number from to begin retrieving of values
   * @param end last row number in the section from which values are retrieved.
   * @return only valid values from rows no. <code>begin</code> through <codE>end</code>, sorted.
   */
  protected Object[] getValuesInRange(int begin, int end) {

    if (end < begin) {
      Object[] retVal = {};
      return retVal;
    }

    int[] indices = VHashService.getIndicesInRange(begin, end, elements);
    Object[] values = new Object[indices.length];
    for (int i = 0; i < indices.length; i++) {
      values[i] = elements.get(indices[i]);
    }
    toComparableArray(values);

    Arrays.sort(values);
    return values;
  }
  /**
   * Returns the values mapped to keys between <code>begin</code> through <code>end</code>, sorted.
   *
   * @param begin Key number from which to begin retrieving of values
   * @param end Greatest key number from which to retrieve value
   * @return Sorted byte array with the values mapped to keys <code>begin
   *         </code> through <code>end</code>.
   */
  public byte[] getValuesInRange(int begin, int end) {

    if (end < begin) {
      byte[] retVal = {};

      return retVal;
    }

    int[] keysInRange = VHashService.getIndicesInRange(begin, end, this);

    if (keysInRange == null) {
      return null;
    }

    byte[] values = new byte[keysInRange.length];

    for (int i = 0; i < keysInRange.length; i++) {
      values[i] = get(keysInRange[i]);
    }

    Arrays.sort(values);

    return values;
  }