'How to get the key by index in Hashtable?

I try to get the value of the key in a Hashtable based on the index position I provide, this is my hashtable:

Hashtable<Integer, String> hash_table = new Hashtable<Integer, String>();
hash_table.put(5, "This");
hash_table.put(7, "Is");
hash_table.put(10, "Hashtable");

To get the value of the key based on the index position, I wrote a method as follows:

public static Integer getKeyByIndex(Hashtable<Integer, String> hashtable, int index) {
    Integer keyValue = null;
    if(index < 0 || index > hashtable.size() - 1) {
        return keyValue;
    }
    Enumeration<Integer> enu = hashtable.keys();
    for(int i = 0; enu.hasMoreElements();) {
        keyValue = enu.nextElement();
        if(i == index) {
            break;
        }
        ++i;
    }
    return keyValue;
}

The above method, although operating correctly, it seems long and has not been optimized. So I want to know if there is a brief way?

I will appreciate the solutions you give.



Solution 1:[1]

As @WJS noted, the correct way to go is with a LinkedHashMap which maintains insertion order (as the iteration order on key/value pairs). As an improvement to solutions proposed, we can extract the i-th key without populating a full array/list of the map keys (which can be rather inefficient) using O(1) memory.

Let map be a LinkedHashMap :

LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
map.put(99,"fu");
map.put(33, "bar");
map.put(5, "foo");

Solution with streams

static <K,V> K getKeyByIndex(LinkedHashMap<K,V> map, int index)
{
    return map.keySet().stream().skip(index).findFirst().orElse(null);
}

Solution with plain iterators

static <K,V> K getKeyByIndex(LinkedHashMap<K,V> map, int index)
{
    final Iterator<K> it = map.keySet().iterator();
    for (int i = 0; i < index && it.hasNext(); ++i) {
        it.next();
    }
    return it.hasNext()? it.next() : null;
}

Solution 2:[2]

Maps don't have the concept of being indexed as the keys are unordered. But you can preserve the insertion order by using a LinkedHashMap. So if you want to get say the nth value you inserted, then the following will work for you.

LinkedHashMap<Integer, String> map = new LinkedHashMap<>();
map.put(5, "This");
map.put(7, "Is");
map.put(10, "Hashtable");
map.put(100,"foo");
map.put(99,"bar");

int v = getKeyByIndex(map, 2);
System.out.println(v);

prints

10
  • LinkedHashMap uses a LinkedKeySet to maintain insertion order.
  • map the keys to an array.
  • and index the array using the supplied index.
  • By using generic type parameters you can use the method for any LinkedHashMap regardless of the key/value types.
@SuppressWarnings("unchecked")
public static <K,V> K getKeyByIndex(LinkedHashMap<K, V> map, int index) {
    K keyValue = null;
    if(index < 0 || index >= map.size()) {
        return keyValue;
    }

    Iterator<K> it = map.keySet().iterator();
    for (int i = 0; i < index; i++) {
        it.next();
    }
    return it.next();
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Michail Alexakis
Solution 2