8

I'm trying to understand if I can get a linked list of entries from my linked hash map. I can get entrySet() and then using iterator I get through each entry in the insertion order. This will give me the linked list of entries in the insertion order.

Can I guarantee the same result if I use the values() method?

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
Rostislav V
  • 1,706
  • 1
  • 19
  • 31
  • 1
    Your question title doesn't really match question which you are asking at the end. Can you [edit] your title to actually be related to answers which you expect to get? – Pshemo Apr 10 '19 at 12:03
  • 4
    `keySet()`, `values()` and `entrySet()` will all three give you internally backed views without additional cost. All of them are just views to the actual internal representation, they all represent the same. In particular, no copies or anything are created, it comes with no real cost. This is documented in Javadoc, please check the documentation first. – Zabuzard Apr 10 '19 at 12:04
  • @Zabuza It's surprisingly hard to find a definite statement about that in the JavaDoc. At least, I did not find something like: "The iteration order of the collection returned by the `values()` method is guaranteed to be the same as the insertion order". This certainly **is** the case, but it is not mentioned so explicitly... – Marco13 Apr 10 '19 at 12:08
  • done, I hope the title is better now @Pshemo – Rostislav V Apr 10 '19 at 12:08
  • 1
    "Get LinkedList of entries .. with values() method" can't be done since `values()` doesn't return entries (as key-value pairs, but only list of values). Your question looks more like "Does LinkedHashMap guarantee same order for entrySet() and values()?" (but I am not sure if that is what you *really* wanted to ask because I still don't know what is the purpose of LinkedList here) – Pshemo Apr 10 '19 at 12:11
  • 1
    @Marco13 I agree that there is no absolute clear statement about that. For me, it is implied by them saying that all returned Collections are views of the map. The map guarantees that iteration order, so the Collections must as well, except stated otherwise, as they are views and as such, must behave the same. – Zabuzard Apr 10 '19 at 12:15
  • 2
    If that is not enough, then it is debatable and, if absolute necessary, should technically not be relied on. However, even if the Java-devs don't see this as documented promised feature, I highly doubt they would ever change that, as it would break an extreme amount of code. – Zabuzard Apr 10 '19 at 12:17
  • @Zabuza Sure, we know that it *is* like that, and we know that thousands of people *do* rely on that, and that it therefore always *will* be like that (otherwise, many implementations would break). Nevertheless, I was a bit surprised to not find it explicitly stated in the JavaDoc. – Marco13 Apr 10 '19 at 12:23
  • 2
    The Iteration order also depends on the constructor you use. Because you could specify if you need accessed order (like an LRU cache) or insertion order. – Laksitha Ranasingha Apr 10 '19 at 12:32

3 Answers3

5

As of Java 8, let's take a look at the source of LinkedHashMap. We can deduct the internal behavior from the entrySet() and values() method definitions:

  • The method entrySet() returns new LinkedEntrySet() on the line 627 which uses new LinkedEntryIterator() as the iterator as of line 634.
  • The method values() returns new LinkedValues() on the line 581 which uses new LinkedValueIterator() as the iterator as of line 588.

Now, let's look at the sources of those inner classes defined in the very same file beginning from line 737:

final class LinkedValueIterator extends LinkedHashIterator
    implements Iterator<V> {
    public final V next() { return nextNode().value; }
}

final class LinkedEntryIterator extends LinkedHashIterator
    implements Iterator<Map.Entry<K,V>> {
    public final Map.Entry<K,V> next() { return nextNode(); }
}

They both extend LinkedHashIterator which implies the accessing of values of the map would be treated the same way using both entrySet() and values().

Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • 1
    It's nice to be able to poke around in the source code. I fully agree with your answer. Nevertheless, I think such things must be mentioned (clearly stated) in the docs, so you don't have to figure it out on your own. – Andrew Tobilko Apr 10 '19 at 13:57
  • @AndrewTobilko: Cannot agree more. The first I looked to was the Java 8 documentation, however, I haven't found anything useful to mention in here. Looking to the source code shall be the last choice after seeing official tutorials, wiki, documentation and unit tests. – Nikolas Charalambidis Apr 10 '19 at 21:25
  • The main point is: This could change in Java 9, 10 or 11, as long it is not part of the contract (API docs). However, this is purely hypothetical, of course: It will **not** change. As long as relying on the iteration order is not relevant for, say, the implementation of an emergency shutdown of a nuclear power plant, one shouldn't worry about that. – Marco13 Apr 12 '19 at 15:14
1

Can I guarantee the same result if I use the values() method?

Basically, LinkedHashMap#values returns you a restricted view of the internal structure. And I'd venture to say it must give the same result. It's not explicitly stated in the docs

Returns a Set view of the mappings contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa.

but the highlighted excerpt makes me think so.

"The same result" is more than a data collection: it includes the way the data should be iterated (the iterator). "changes to the map are reflected in the set" to me implies that both iterators share one algorithm, which, on the same piece of data, would result in the same behaviour.

Andrew Tobilko
  • 48,120
  • 14
  • 91
  • 142
0

I think so. Internally the class uses java.util.LinkedHashMap.LinkedHashIterator, which is used by both entrySet() and values(), so if the former allows you to iterate in the insertion order, the latter will do the same.

Pateman
  • 2,727
  • 3
  • 28
  • 43
  • I also "think so" (and basically "know" it, also by looking at the code). But looked up the JavaDocs and didn't see an **explicit** guarantee. What comes closest to a guarantee is the statement *""The spliterators returned by ... the collections returned by .... collection view methods ... report Spliterator.ORDERED"* ... – Marco13 Apr 10 '19 at 12:06
  • I agree totally. – Pateman Apr 10 '19 at 12:08