Why does HashSet <E> not limit the type of argument E to contains () and remove ()
Possible duplicate:
What are the reasons why Map.get (the object key) is not (fully) shared
Why Java TreeSet <E> remove (Object) does not accept E
Why the HashSet does not limit the type of argument E here:
public boolean contains(Object o) public boolean remove(Object o) as for add ()
public boolean add(E e) I mean, if the compiler forcibly establishes that only objects of type E are added, then the set cannot contain / delete any other type
The difference is that the addition must be safe for storage in order to preserve the integrity of the collection, while checking / deleting elements can afford to "forgive the type" without risking damage to the security of the type of collection. In other words, if you add an element of the wrong type, the set will become invalid; on the other hand, if you check for an element of the wrong type, you will simply return false . The same goes for remove : if you pass an element of an incompatible type, it will not be in the set + so removal will not work.
+ If you do not enter it through a hack that uses type erasure.
then the set cannot contain / delete any other type
Of course it can. Read about the erase dash, or add a HashSet<E> to a non-generic HashSet and add an object that is not of type E .
Check this code:
Integer testInt = new Integer(3); // First, create a generic set of strings HashSet<String> set = new HashSet<String>(); set.add("abc"); // Then make it non-generic and add an integer to it ((HashSet) set).add(testInt); // Now your set-of-strings contains an integer! System.out.println(set); // prints: [abc, 3] // Remove the integer set.remove(testInt); System.out.println(set); // prints: [abc] The reason for this oddity is that information about common types is erased at runtime, and your set becomes a simple set of objects.
The contains and remove parameter cannot be restricted to E , because you must give them equal objects, which is very useful. More specifically, the HashSet.remove API says:
... More formally removes an element e such that (o == null? E == null: o.equals (e)) if this set contains such an element.
Object.equals takes an Object parameter as a parameter, which is also very useful for ensuring equality between the various types.
Thus, in order to provide more general functionality for contains and remove (on equivalence classes, and not just on the identity of an object), they should take Object as a parameter.
Example:
HashSet<ArrayList<String>> set = new HashSet<ArrayList<String>>(); ArrayList<String> list = new ArrayList<String>(); list.add("foo"); LinkedList<String> equalList = new LinkedList<String>(); equalList.add("foo"); set.add(list); System.out.println(list.equals(equalList)); // prints: true System.out.println(set.contains(equalList)); // prints: true System.out.println(set); // prints: [[foo]] set.remove(equalList); System.out.println(set); // prints: [[]]