content: package zemberek.core.collections;
  
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.List;
  
  /**
   * A map like structure that has unsigned integer keys and T values.
   */
  public class UIntMap<T> extends UIntKeyHashBase implements Iterable<T> {
  
    private T[] values;
  
    public UIntMap() {
      this(INITIAL_SIZE);
    }
  
    public UIntMap(int size) {
      super(size);
      values = (T[]) new Object[keys.length];
    }
  
    /**
     * Returns the value for the key. If key does not exist, returns 0.
     *
     * @param key key
     * @return count of the key
     */
    public T get(int key) {
      if (key < 0) {
        throw new IllegalArgumentException("Key cannot be negative: " + key);
      }
      int slot = hash(key) & modulo;
      while (true) {
        final int t = keys[slot];
        if (t == EMPTY) {
          return null;
        }
        if (t == DELETED) {
          slot = (slot + 1) & modulo;
          continue;
        }
        if (t == key) {
          return values[slot];
        }
        slot = (slot + 1) & modulo;
      }
    }
  
    public boolean containsKey(int key) {
      return locate(key) >= 0;
    }
  
    private void expand() {
      UIntMap<T> h = new UIntMap<>(values.length * 2);
      for (int i = 0; i < keys.length; i++) {
        if (keys[i] >= 0) {
          h.put(keys[i], values[i]);
        }
      }
      copyParameters(h);
      this.values = h.values;
    }
  
    /**
     * puts `key` with `value`. if `key` already exists, it overwrites its value with `value`
     */
    public void put(int key, T value) {
      if (key < 0) {
        throw new IllegalArgumentException("Key cannot be negative: " + key);
      }
      if (keyCount + removeCount == threshold) {
        expand();
      }
      int loc = locate(key);
      if (loc >= 0) {
        values[loc] = value;
      } else {
        loc = -loc - 1;
        keys[loc] = key;
        values[loc] = value;
        keyCount++;
      }
    }
  
    public List<T> getValues() {
      List<T> result = new ArrayList<>();
      for (int i = 0; i < keys.length; i++) {
        int key = keys[i];
        if (key >= 0) {
          result.add(values[i]);
        }
      }
      return result;
    }
  
    @Override
    public Iterator<T> iterator() {
      return new ValueIterator();
    }
  
    /**
     * returns the values sorted ascending.
     */
    public List<T> getValuesSortedByKey() {
      int[] sortedKeys = getKeyArraySorted();
      List<T> result = new ArrayList<>(sortedKeys.length);
      for (int sortedKey : sortedKeys) {
        result.add(get(sortedKey));
      }
      return result;
    }
  
    private class ValueIterator implements Iterator<T> {
  
      int keyCounter = 0;
      int counter = 0;
      T item;
  
      @Override
      public boolean hasNext() {
        if (counter == keyCount) {
          return false;
        }
        while (true) {
          if (keys[keyCounter] >= 0) {
            keyCounter++;
            break;
          }
          keyCounter++;
        }
        item = values[keyCounter - 1];
        counter++;
        return true;
      }
  
      @Override
      public T next() {
        return item;
      }
    }
  
  }
  