1

Is there a way of iterating a LinkedHashMap (which has a defined order) by using an index instead of a foreach loop? I need to access elements using index.

The following code prints the entire map:

public void print(Map<String, Integer> map)
{
    for (Map.Entry<String, Integer> entryMap : map.entrySet())
    {
        System.out.println(entryMap.getValue() + " = " + entryMap.getKey());
    }
}

How can I do the same but access the elements using index instead?

public void print(Map<String, Integer> map)
{
    for (int i = 0; i< map.size(); i++)
    {
        // getValue() and getKey() are undefined
        System.out.println(map.get(i).getValue() + " = " + map.get(i).getKey());
    }
}

The following only returns the keys, but I also need the values:

public String getByIndex(Map<String, Integer> map, int index)
{
    List<String> keys = new ArrayList<>(map.keySet());

    return (String) keys.get(index);
}
BullyWiiPlaza
  • 17,329
  • 10
  • 113
  • 185
  • 1
    duplicate of the duplicate at http://stackoverflow.com/questions/13581997/how-get-value-from-linkedhashmap-based-on-index-not-on-key – austin wernli Nov 05 '14 at 20:01
  • `LinkedHashMap` retains the insert order, so iterating over its `values()` using enhanced for loop should give you the elements in the same order you have put them. If you need a counter just define it ouside the for loop in increment it inside. – A4L Nov 05 '14 at 20:02
  • Do you just need the indices while you're processing the entries, or do you need random access? If the former, you could create a Pair class and a stream of `Pair>` values, and then you don't need to build a complete parallel copy. If the latter, iterate the `entrySet()` and put the values into an `ArrayList>`. – David Conrad Nov 05 '14 at 20:10

3 Answers3

3

Try this :

List<String> keys = new ArrayList(map.keySet());
for (int i = 0; i < keys.size(); i++)
{
    String key = keys.get(i);
    Integer value = map.get(key);
    //...
}
ToYonos
  • 16,469
  • 2
  • 54
  • 70
2

Well you can write a method to do this.

public static <K, V> Map.Entry<K, V> getEntryByIndex(Map<K, V> map, int i) {
    if(i >= map.size()) {
        throw new IndexOutOfBoundsException(String.valueOf(i));
    }

    // use Iterator
    Iterator<Map.Entry<K, V>> it = map.entrySet().iterator();

    // skip to i
    for(; i > 0; --i) {
        it.next();
    }

    return it.next();
}

This pretty much treats it like a linked list. If you are finding you do this a lot you may want to permanently keep an ArrayList along with the Map.

Radiodef
  • 37,180
  • 14
  • 90
  • 125
0

One of the possible workarounds would be to put all keys also into ArrayList where they can be accessed using index. Direct access seems not possible because keySet returns a set that does not support the indexed access.

Audrius Meškauskas
  • 20,936
  • 12
  • 75
  • 93