117

How to retrieve an element from HashMap by its position, is it possible at all?

jzd
  • 23,473
  • 9
  • 54
  • 76
Eugene
  • 59,186
  • 91
  • 226
  • 333
  • 11
    What do you mean by "position"? HashMaps are not ordered, so they do not have the usual notion of "position" that you would get with something like a Vector. – Mat Mar 08 '11 at 19:15
  • 1
    Do you mean by its insertion order or some other ordering? – Mark Elliot Mar 08 '11 at 19:16

14 Answers14

119

Use a LinkedHashMap and when you need to retrieve by position, convert the values into an ArrayList.

LinkedHashMap<String,String> linkedHashMap = new LinkedHashMap<String,String>();
/* Populate */
linkedHashMap.put("key0","value0");
linkedHashMap.put("key1","value1");
linkedHashMap.put("key2","value2");
/* Get by position */
int pos = 1;
String value = (new ArrayList<String>(linkedHashMap.values())).get(pos);
serg
  • 109,619
  • 77
  • 317
  • 330
Kulnor
  • 1,217
  • 1
  • 8
  • 5
104

HashMaps do not preserve ordering:

This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time.

Take a look at LinkedHashMap, which guarantees a predictable iteration order.

Shaishav
  • 5,282
  • 2
  • 22
  • 41
Wayne
  • 59,728
  • 15
  • 131
  • 126
58

If you want to maintain the order in which you added the elements to the map, use LinkedHashMap as opposed to just HashMap.

Here is an approach that will allow you to get a value by its index in the map:

public Object getElementByIndex(LinkedHashMap map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
}
Dave Jarvis
  • 30,436
  • 41
  • 178
  • 315
Syd Lambert
  • 1,415
  • 14
  • 16
24

If you, for some reason, have to stick with the hashMap, you can convert the keySet to an array and index the keys in the array to get the values in the map like so:

Object[] keys = map.keySet().toArray();

You can then access the map like:

map.get(keys[i]);
Bill Wang
  • 140
  • 13
theNoble247
  • 460
  • 5
  • 12
12

Use LinkedHashMap:

Hash table and linked list implementation of the Map interface, with predictable iteration order. This implementation differs from HashMap in that it maintains a doubly-linked list running through all of its entries.

Grimthorr
  • 6,856
  • 5
  • 41
  • 53
ilalex
  • 3,018
  • 2
  • 24
  • 37
  • 27
    that will preserve the order, but you still can't access items by their index. You'd have to iterate – Bozho Mar 08 '11 at 19:17
  • this link is to a old version of the API. I would suggest linking to a Java 6 or 7 API. – jzd Mar 08 '11 at 19:19
6

Use LinkedHashMap and use this function.

private LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();

Define like this and.

private Entry getEntry(int id){
        Iterator iterator = map.entrySet().iterator();
        int n = 0;
        while(iterator.hasNext()){
            Entry entry = (Entry) iterator.next();
            if(n == id){
                return entry;
            }
            n ++;
        }
        return null;
    }

The function can return the selected entry.

Jeff Lee
  • 783
  • 9
  • 17
4

By default, java LinkedHasMap does not support for getting value by position. So I suggest go with customized IndexedLinkedHashMap

public class IndexedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private ArrayList<K> keysList = new ArrayList<>();

    public void add(K key, V val) {
        super.put(key, val);
        keysList.add(key);
    }

    public void update(K key, V val) {
        super.put(key, val);
    }

    public void removeItemByKey(K key) {
        super.remove(key);
        keysList.remove(key);
    }

    public void removeItemByIndex(int index) {
        super.remove(keysList.get(index));
        keysList.remove(index);
    }

    public V getItemByIndex(int i) {
        return (V) super.get(keysList.get(i));
    }

    public int getIndexByKey(K key) {
        return keysList.indexOf(key);
    }
}

Then you can use this customized LinkedHasMap as

IndexedLinkedHashMap<String,UserModel> indexedLinkedHashMap=new IndexedLinkedHashMap<>();

TO add Values

indexedLinkedHashMap.add("key1",UserModel);

To getValue by index

indexedLinkedHashMap.getItemByIndex(position);
Vikram Kodag
  • 485
  • 5
  • 6
3

Another working approach is transforming map values into an array and then retrieve element at index. Test run of 100 000 element by index searches in LinkedHashMap of 100 000 objects using following approaches led to following results:

//My answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.values().toArray(new Particle[map.values().size()])[index];
} //68 965 ms

//Syd Lambert's answer:
public Particle getElementByIndex(LinkedHashMap<Point, Particle> map,int index){
    return map.get( (map.keySet().toArray())[ index ] );
} //80 700 ms

All in all retrieving element by index from LinkedHashMap seems to be pretty heavy operation.

user3738243
  • 159
  • 2
  • 13
3

I'm assuming by 'position' you're referring to the order in which you've inserted the elements into the HashMap. In that case you want to be using a LinkedHashMap. The LinkedHashMap doesn't offer an accessor method however; you will need to write one like

public Object getElementAt(LinkedHashMap map, int index) {
    for (Map.Entry entry : map.entrySet()) {
        if (index-- == 0) {
            return entry.value();
        }
    }
    return null;
}
homebrew
  • 101
  • 6
2

HashMap - and the underlying data structure - hash tables, do not have a notion of position. Unlike a LinkedList or Vector, the input key is transformed to a 'bucket' where the value is stored. These buckets are not ordered in a way that makes sense outside the HashMap interface and as such, the items you put into the HashMap are not in order in the sense that you would expect with the other data structures

dfb
  • 13,133
  • 2
  • 31
  • 52
2

HashMap has no concept of position so there is no way to get an object by position. Objects in Maps are set and get by keys.

Robby Pond
  • 73,164
  • 16
  • 126
  • 119
2

HashMaps don't allow access by position, it only knows about the hash code and and it can retrieve the value if it can calculate the hash code of the key. TreeMaps have a notion of ordering. Linkedhas maps preserve the order in which they entered the map.

fastcodejava
  • 39,895
  • 28
  • 133
  • 186
2

you can use below code to get key : String [] keys = (String[]) item.keySet().toArray(new String[0]);

and get object or list that insert in HashMap with key of this item like this : item.get(keys[position]);

mahsa k
  • 555
  • 6
  • 9
0

You can try to implement something like that, look at:

Map<String, Integer> map = new LinkedHashMap<String, Integer>();
map.put("juan", 2);
map.put("pedro", 3);
map.put("pablo", 5);
map.put("iphoncio",9)

List<String> indexes = new ArrayList<String>(map.keySet()); // <== Parse

System.out.println(indexes.indexOf("juan"));     // ==> 0
System.out.println(indexes.indexOf("iphoncio"));      // ==> 3
Dharman
  • 30,962
  • 25
  • 85
  • 135