I was looking at the API for the java.util.Map interface and I noticed that a lot of its methods aren't entirely Generic. I was was wondering why that is. These methods are:

boolean containsKey(Object)

boolean containsValue(Object)

V get(Object)

V remove(Object)

Is there any particular reason why it's better than making all the methods Generic? like a performance reason?

If it's for backwards compatibility, I thought that Generics automatically defaults to the class that it extends from if it's running on an older Java (for example, Collection<E> defaulting to Collection, or <N extends Number> N defaulting to Number.)

For specific details on what I was doing, I was trying to make a java.util.Map that's also a java.util.Collection just for the sake of an exercise. And I was having trouble with the Map's V remove(Object key)
method, which makes the Map interface incompatible with Collection's boolean remove(Object o).

To be fair, java.util.Collection<E> isn't entirely Generic, but I am asking myself now if this is something that I should consider implementing in Generic classes as well, or if it's better to have a completely Generic class (when needed, of course) like I originally thought.

My general question is, why make it only partially Generic instead of going the full way with Generics or leaving it un-generic.

Parameterizing a collection with type T means you can only add Ts to it. The point is to prevent you (at compile time) from inadvertently adding a Q to it, and to ensure (at compile time) that when you get something out of it, it will be a T. If you try to add a Q, the compiler will give you an error.

However, there's no harm in, for instance, testing whether a Q is present. Of course the answer will always be false, but it doesn't interfere with your desired functionality (only allowing Ts into the collection) to do the test.

There may also have been reasons why it was necessary or significantly easier to retrofit them this way, but I don't know and I'm not really interested in pursuing that question.

It would have broken a lot of existing code to make those methods accept T instead of Object. Their contracts only say in effect that they must be equal and hashCode-equal to the object wanted, not that they must be of the same type.