12

From Javadoc:
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.

If it is so, then why doesn't it provide object access like List in java, list.get(index);

UPDATE

I had implemented LRU Cache using LinkedHashMap. My algorithm required me to access LRU Object from the cache. That's why I required random access, but I think that will cost me bad performance, so I have changed the logic and I am accessing the LRU object just when Cache is full...using removeEldestEntry()

Thank you all...

Eternal Noob
  • 2,717
  • 5
  • 27
  • 41

5 Answers5

15

a) Because the entries are linked, not randomly accessible. The performance would be miserable, O(N) if I'm not in error.

b) Because there is no interface to back up this functionality. So the choice would be to either introduce a dedicated interface just for this (badly performing) Implementation or require clients to program against implementation classes instead of interfaces


Btw with Guava there's a simple solution for you:

Iterables.get(map.values(), offset);

And for caching look at Guava's MapMaker and it's expiration features.

Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • Thanks Sean. I'm using LinkedHashMap for implementing LRU Cache...and wanted some functionality to peek LRU object...but I guess iterating over map would be very bad performance...Do you know any other data structure for such functionality? – Eternal Noob Apr 14 '11 at 17:21
  • 3
    +1, good answer. However, it should be noted that it wouldn't be any worse than the performance provided by, say, `LinkedList`, so I don't really see the argument. – aioobe Apr 14 '11 at 17:22
  • 1
    @Eternal Noob, it says in the docs: *This kind of map is well-suited to building LRU caches.*, and, *iterating* over the map is as efficient as it gets (O(n)) – aioobe Apr 14 '11 at 17:39
  • 1
    @aioobe which is why LinkedList doesn't implement RandomAccess – Sean Patrick Floyd Apr 14 '11 at 17:49
7

Since values() provides a backing collection of the values, you can solve it like this:

map.values().remove(map.values().toArray()[index]);

Perhaps not very efficient (especially memory-wise), but it should be O(N) just as you would expect it to be.


Btw, I think the question is legitimate for all List operations. (It shouldn't be slower than LinkedList anyway, right?)

I set out to do a LinkedHashMapList which extended the LinkedHashMap and implemented the List interface. Surprisingly it seems impossible to do, due to the clash for remove. The existing remove method returns the previously mapped object, while the List.remove should return a boolean.

That's just a reflection, and honestly, I also find it annoying that the LinkedHashMap can't be treated more like a LinkedList.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • ya, I saw that too... remove() method for LinkedHashMap is coming from HashMap as LinkedHashMap extends HashMap...and that's conflicting with List's remove()... – Eternal Noob Apr 14 '11 at 17:25
1

It provides an Iterator interface, each node in the list is linked to the one before it and after it. Having a get(i) method would be no different than iterating over all the elements in the list since there is no backing array (same as LinkedList).

If you require this ability which isn't very performant I suggest extending the map yourself

Asaf
  • 6,384
  • 1
  • 23
  • 44
  • So, in linked list, whenever we access last element, list.get(list.size()-1), is it a random access or O(n) (all the elements are iterated)? – Eternal Noob Apr 14 '11 at 17:10
  • 3
    `It provides an Iterator interface` that's not correct. The map's entrySet() provides the iterator, not the Map itself (but apart from that you're right) – Sean Patrick Floyd Apr 14 '11 at 17:11
  • 1
    @EternalNoob it’s an old comment, but for future readers it’s worth answering your old question: the `LinkedList` knows its size and will iterate backwards when you access an element index higher than the list’s half. So accessing the last element is as cheap as accessing the first element. Only elements in the middle have the expense of iteration. – Holger Dec 09 '19 at 09:59
1

If you want random access you can do

Map<K,V> map = new LinkedHashMap<K,V>();
Map.Entry<K,V>[] entries = (Map.Entry<K,V>[]) map.toArray(new Map.Entry[map.size()]);
Map.Entry<K,V> entry_n = entry[n];

As you can see the performance is likely to be very poor unless you cache the entries array.

I would question the need for it however.

par
  • 17,361
  • 4
  • 65
  • 80
Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
0

There is no real problem to make a Map with log(N) efficiency of access by index. If you use a red-black tree and store for each node the number of elements in the tree starting at that node it is possible to write a get(int index) method that is log(N).