Brandon Ling
Brandon Ling

Reputation: 3919

Why doesn't LinkedHashMap keyset() return LinkedHashSet vs Set?

I've read in java documentation and also in this post that LinkedHashMaps' keyset() maintains order. Is the order guaranteed for the return of keys and values from a LinkedHashMap object?

My question is, if it guarantees order then why doesn't the source code of LinkedHashMap return an Object of type Set that guarantees order like LinkedHashSet?

One reason I can maybe think of is that LinkedHashSet uses a map which would increase memory allocation (depending on how AbstractSet is implemented). Is it also because it future proofs implementation of keyset?

Like this answer says in this post : Is it better to use List or Collection?

Returning a List is in line with programming to the Highest Suitable Interface.

Returning a Collection would cause ambiguity to the user, as a returned collection could be either: Set, List or Queue.

So, without reading the documentation of the keyset() isn't this ambiguous?

keyset() source code:

public Set<K> keySet() {
    Set<K> ks = keySet;
    return (ks != null ? ks : (keySet = new KeySet()));
}

private final class KeySet extends AbstractSet<K> {
    public Iterator<K> iterator() {
        return newKeyIterator();
    }
    public int size() {
        return size;
    }
    public boolean contains(Object o) {
        return containsKey(o);
    }
    public boolean remove(Object o) {
        return HashMap.this.removeEntryForKey(o) != null;
    }
    public void clear() {
        HashMap.this.clear();
    }
}

Upvotes: 3

Views: 2636

Answers (4)

M. Justin
M. Justin

Reputation: 21399

Java 21 added the sequencedKeySet method to LinkedHashMap, which returns the key set as a SequencedSet (i.e. a Set with a well-defined encounter order). While the keySet method continues to be a Set to maintain backwards compatibility, the sequencedKeySet method returns the SequencedKeySet type that specifically guarantees a well-defined iteration order.

Upvotes: 0

John Bollinger
John Bollinger

Reputation: 181849

if it guarantees order then why doesn't the source code of LinkedHashMap return an Object of type Set that guarantees order like LinkedHashSet?

The declared type of the key set is drawn from that declared by Map.keySet(). LinkedHashMap was added to the standard library before covariant return types were added to the Java language. At that time, there was no alternative to using type Set.

In any event, just because the key set must have the same order as the underlying map does not mean that it must be a LinkedHashSet, and in fact it cannot be, because it must not support element additions. Its class is instead a private nested class of class LinkedHashMap. There is no public type between that class and Set that would be any more useful than Set as a return type.

Indeed, I don't think it would be easy to define one. What would be the essential characteristics that distinguish it from any other set? You cannot merely say "iteration order" without specifying what iteration order instances would have, and that order depends on the LinkedHashMap instance from which the set is obtained. In other words, iteration order is an instance characteristic, not a class characteristic. A declared type that expresses the nature of being the key set of a LinkedHashMap would therefore provide almost no information of any practical use beyond what Set provides.

Anyway, I do not find the excerpt you quoted about returning a List vs a Collection to be very persuasive. The fact is that ambiguity about an object's specific class is not inherently a problem. In the Collection vs. List example, if type Collection captures the return-type requirements of the method well, such that there is no particular reason that the characteristic features of a List are required, then Collection is a good choice of return type. It is especially good if the requirements could also be satisfied by a Set, because then the API is not making an essentially arbitrary choice between two equally good alternatives.

There is a school of thought that holds that methods should be as general as possible in the types of their arguments and as specific as possible in their return types. I attribute a lot of merit to that idea, but it is rather more of a guideline than a rule, and there is quite a lot of room for interpretation as to how specific "as specific as possible" is.

Upvotes: 1

Andreas
Andreas

Reputation: 159260

"why doesn't the source code of LinkedHashMap return an Object of type Set that guarantees order like LinkedHashSet?"

Because LinkedHashSet is a concrete class with it's own implementation maintaining its own data, and the keyset() method must return a view of the Map, so it cannot just copy the key data to a LinkedHashSet. See javadoc:

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

Upvotes: 6

Austin
Austin

Reputation: 8585

It returns a Set as defined by the Map interface. A Set is simply collection that contains no duplicate elements. On the other hand, a List is an ordered collection (also known as a sequence). The List interface does not specify that elements be unique.

Still, the LinkedHashMap implementation actually returns the underlying keySet which is a LinkedKeySet, and the forEach() method of the LinkedKeySet is order-preserving, i.e.:

//from the source code for the LinkedHashMap:
public Set<K> keySet() {
    Set<K> ks;
    return (ks = keySet) == null ? (keySet = new LinkedKeySet()) : ks;
}

So, in this case, the elements are both unique and ordered.

Upvotes: 5

Related Questions