Рассмотрите возможность создания составной структуры данных для этого. На высоком уровне сделайте следующее.
Во-первых, реализуйте Map.Entry, чтобы сохранить пары ключ-значение. Порядок пары будет сначала по значению, а затем по ключу.
private static class InternalEntry<K extends Comparable<K>,
V extends Comparable<V>>
implements Comparable<InternalEntry<K, V>>,
Map.Entry<K, V> {
private final K _key;
private final V _val;
InternalEntry(K key, V val) {
_key = key;
_val = val;
}
public K getKey() {
return _key;
}
public V getValue() {
return _val;
}
public V setValue(V value) {
throw new UnsupportedOperationException();
}
public int compareTo(InternalEntry<K, V> o) {
int first = _val.compareTo(o._val);
if (first != 0) {
return first;
}
return _key.compareTo(o._key);
}
}
Вся запись может использоваться в качестве клавиши заказанной карты.
Но эта карта не поддерживает эффективный поиск значения по ключу. Для этого введите еще одну карту, которая сопоставляет ключи с записями.
Составная структура выглядит следующим образом:
class OrderedByValue<K extends Comparable<K>, V extends Comparable<V>> {
private final Map<InternalEntry<K, V>, Boolean> _ordering =
new TreeMap<InternalEntry<K, V>, Boolean>();
private final Map<K, InternalEntry<K, V>> _lookup =
new HashMap<K, InternalEntry<K, V>>();
public V put(K key, V val) {
InternalEntry<K, V> entry = new InternalEntry<K, V>(key, val);
InternalEntry<K, V> old = _lookup.put(key, entry);
if (old == null) {
_ordering.put(entry, Boolean.TRUE);
return null;
}
_ordering.remove(old);
_ordering.put(entry, Boolean.TRUE);
return old.getValue();
}
@SuppressWarnings({"unchecked"})
public Iterable<Map.Entry<K, V>> entrySet() {
Iterable entries = Collections.unmodifiableSet(_ordering.keySet());
return (Iterable<Map.Entry<K, V>>) entries;
}
}
Обратите внимание, что я не предоставил весь необходимый код для реализации полной карты - дайте мне знать, если вам нужна помощь с другими методами.
Вам также нужно сделать какой-то особый код в реализации сравнения InternalEntry, если необходимо поддерживать нулевые ключи / значения.