58

I have

LinkedHashMap<String, List<String>> hMap;

I want to get List<String> by position not on key.

I don't want to use iterate.

Is there any other way to get Value based on index ?

MAC
  • 15,799
  • 8
  • 54
  • 95

5 Answers5

61

You can't get the value of the Map based on index, Maps just don't work that way. A workaround would be to create a new list from your values and get the value based on index.

LinkedHashMap<String, List<String>> hMap;
List<List<String>> l = new ArrayList<List<String>>(hMap.values());
l.get(0);
Intrications
  • 16,782
  • 9
  • 50
  • 50
PermGenError
  • 45,977
  • 8
  • 87
  • 106
23
public List<String> getByIndex(LinkedHashMap<String, List<String>> hMap, int index){
   return (List<String>) hMap.values().toArray()[index];
}
Kevin Bowersox
  • 93,289
  • 19
  • 159
  • 189
16

you may want to consider either using another class to store your data, or write an extension to the linkedHashMap. something like

//this is pseudo code
public class IndexedLinkedHashMap<K,V> extends LinkedHashMap{

HashMap<int,K> index;
int curr = 0;

    @Override
    public void add(K key,V val){
        super.add(key,val);
        index.add(curr++, key);
    }

    public V getindexed(int i){
        return super.get(index.get(i));
    }

}
schippi
  • 1,034
  • 5
  • 15
  • This seems to be by far the best method, but I don't see the purpose of the variable `curr`. – Hasen Sep 06 '22 at 00:32
9

As Kevin Bowersox stated, it's as simple as

List<String> result = (List<String>) hMap.values().toArray()[position];

But it should be noted that this will still iterate by using .toArray(). It's a simple statement and I'm not sure if there is one with better performance, but be aware that complexity is not log(n) (like indexed access in case of B*), but just n. Since LinkedHashMap is based on LinkedList, there is no way to randomly access elements, only in sequential order.

The cast to List is an unavoidable evil, since .toArray() follows the archaic concept of returning Object instead of a generic data type.

While this might not be the main concept of a map, LinkedHashMap isn't just a map. it extends HashMap, and as an extending class, it's perfectly fine to bring additional methods that support the idiosyncracies of that class.

makrom
  • 346
  • 2
  • 12
  • 1
    create a new array .. not very pretty – mjs Jul 31 '15 at 15:02
  • 1
    Here is an answer I posted to this anyhow, I can't post it here, this thread is locked: http://stackoverflow.com/a/31749969/961018 – mjs Jul 31 '15 at 15:49
  • @momo My post was simply meant to explain that what Kevin Bowersox proposed doesn't avoid iteration and furthermore that there's no such way. The creation of an array can easily be avoided by iterating the values manually, but that's not the ideal answer when the question is how to do it without iterating. Obviously you can avoid that by creating your own implementations with a different indexing concept, but that seems unrelated to the question. – makrom Oct 26 '15 at 17:12
5

There is no direct DS in the standard Java Collections API to provide a indexed map. However, the following should let you achieve the result:

// An ordered map
Map<K, V> map = new LinkedHashMap<K, V>();
// To create indexed list, copy the references into an ArrayList (backed by an array)
List<Entry<K, V>> indexedList = new ArrayList<Map.Entry<K, V>>(map.entrySet());
// Get the i'th term
<Map.Entry<K,V>> entry = indexedList.get(index);
K key = entry.getKey();
V value = entry.getValue();

You might still want to retain the concerns of data persistence in the map separate from the retrieval.

Update: Or use LinkedMap from Apache Commons.

LaurentY
  • 7,495
  • 3
  • 37
  • 55
Neel
  • 2,100
  • 5
  • 24
  • 47