There are two aspects to this question that I felt were too closely related to ask as separate questions.
- Why doesn't
SortedMap
implementIterable<Map.Entry<K,V>>
?
If you need to perform an action on every key-value pair in a map, iterating over the entrySet() seems like the way to go. So why not provide a direct iterator() method on SortedMap? Unless you are worried about iteration order being inconsistent in a HashMap. Which leads me to:
- Does implementing
Iterable
imply a stable ordering?
Iterating over an ordered collection (List, SortedMap, SortedSet) is a great way to reliably implement equals() (see Note 1) and do other things that have to produce the same result every time. Iterating over an unsorted set or map could yield different ordering if you call it multiple times, so is unsuitable for these purposes. Especially if you are comparing HashSets or HashMaps – two of them could contain the same objects, but the order of their iterators would be different.
I guess there are 2 aspects to those questions:
-
What are the historical reasons for these design decisions?
-
If doing it again today, are there correct answers to these questions? Maybe
OrderedIterable
should extendIterable
to guarantee order?
Notes:
- I had originally suggested that you needed a reliable ordering to implement hashCode(), but if you sum all the hashcodes, it turns out that you don't need a reliable ordering if your hashing algorithm is commutative. Addition is commonly used for hashCodes and it is commutative: a + b = b + a and B. even with overflow, addition is still commutative so that a + Integer.MAX_VALUE = Integer.MAX_VALUE + a. You do still need a reliable ordering to implement equals() so that you can compare the first item of one to the first item of the other, etc.
P.S.
This question is about the interfaces Iterable
, Set
, SortedSet
, Map
, and SortedMap
. It's fine to bring up other interfaces as examples, but
I do not think the Collection
interface is relevant to this question. It's quirky and has the potential to be a distraction.
Best Answer
Although it is correct from a narrowly technical point of view to say that
Set
implementsIterable
, butSortedMap
does not, it is not a very useful question to ask. A more useful question to ask is whether both classes offer theIterable
interface, and they certainly both do.As you know, there are three ways to offer an interface:
implements
keyword.Set
is declared as follows:public interface Set<E> extends Collection<E> {...
so, as you can see,Set
does not directly implementIterable
, it only implements it indirectly, by virtue of implementingCollection
, which extendsIterable
.Now,
SortedMap
would also be implementingIterable
indirectly, just asSet
does, if it was implementingCollection
, but it does not even do that. Instead, it exposes anentrySet()
function, which returns aCollection
, which extendsIterable
.So, you can have your much desired
Iterable
in both cases.If you would like to insist on the narrowly technical question of why
Set
(indirectly) implementsIterable
, butSortedMap
offers it via a function instead, the answer is that the designers of the java language runtime made the decision a long time ago to refrain from making extensive use of interfaces extending other interfaces. That's whyMap<K,V>
does not extendCollection<Map.Entry<K,V>>
, offering anentrySet()
method instead.They could have done the opposite, and as a matter of fact the designers of the C# language runtime did choose to go the other way, so
IDictionary<K,V>
extendsICollection<KeyValuePair<K,V>>
.I have experimented with both ways, and I still have not arrived at a conclusive decision as to which one is better. They simply appear to be two different ways of accomplishing the same thing.
The implementation of
Iterator
does not imply a stable ordering, as you seem to understand (and therefore it is not clear to me where your question is in that respect.) You may iterate over an unsorted map, in which case nobody can tell what the order of the items will be, and you may insert an element to the map and re-iterate, in which case the order of the items may be completely different from the previous time. (Not just different by one item: all items may appear to be re-arranged.)There is no need for an
OrderedIterable
interface because its signature would be identical toIterable
. (And don't get me started on the choice of the java people to introduce aSet
besidesCollection
.) You can just invokeOrderedMap.entrySet()
, which the documentation promises will return an ordered set, which means that theIterator
of that set will always yield items in order.