Re: HashMap get/put
Mike Schilling wrote:
I can picture (vaguely) looking something up with an object that's
equal to the original key but not of the same type. This makes at
least some sense with HashMaps, since it's possible, for objects T1 a
and T2 b, where T1 and T2 are any types at all, that a.equals(b) and
a.hashCode() == b.hashCode().
Lew wrote:
I don't think so, not in general nor commonly. Someone who codes
disparate types that way should be slapped, then fired.
Patricia Shanahan wrote:
That is correct if "disparate" is read as meaning distinct types that do
are not sufficiently related that objects of the two types might be equal=
..
Yes, that's what I meant. Your example of different implementations
for 'List' would not be "disparate" in this sense.
Lew:
Remember, to work properly 'equals()' must be reflexive, symmetric and
transitive. However, you are right that it's possible to violate that=
..
Patricia:
It is possible to have equals methods that allow equality to an object
of a different type, not a subclass or superclass, that is still
reflexive, symmetric, and transitive.
Consider, for example, ArrayList and Stack. They both conform to the
java.util.List interface, including its documentation for equals:
"Returns true if and only if the specified object is also a list, both
lists have the same size, and all corresponding pairs of elements in the
two lists are equal."
These types are not completely disparate, but even to the degree to
which they are they adhere to the key requirements as you point out.
They also provide a strong argument for 'Map#get(Object)' instead of
'Map#get(E)'.
The really, really, basic rule about equals is 'Indicates whether some
other object is "equal to" this one.'. One would need a breach of that
rule to get a false match from HashMap's get.
The decision to leave get accepting Object means that one can still
probe a Map<Stack, String> with an ArrayList, and get a match if, only
if, the Map contains a key that has equal elements in the same order as
the ArrayList.
Lew:
The common idiom for 'equals()' checks that the argument is of the
same type as the invoker.
Patricia:
The more general version of this rule is to test for types of objects
that might be logically equal to this one. A List equals() method should
test whether its argument is a List, not whether it is the same type as
the specific List implementation.
Excellent points that explain why Java might not have wanted to
genericize 'Map#get()'. They might've done better with some sort of
bounded wildcard argument, but 'Object' works just fine.
The key insight from your example is that for the purpose of
comparison, 'List' implementations are viewed at the level of the
interface type, and not at the level of the concrete type. At that
level, 'ArrayList' and 'Stack' are not disparate.
--
Lew