5

When I see the Set.java file in JDK,

/**
 *
 * <p>This interface is a member of the
 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
 * Java Collections Framework</a>.
 *
 * @param <E> the type of elements maintained by this set
 *
 * @author  Josh Bloch
 * @author  Neal Gafter
 * @see Collection
 * @see List
 * @see SortedSet
 * @see HashSet
 * @see TreeSet
 * @see AbstractSet
 * @see Collections#singleton(java.lang.Object)
 * @see Collections#EMPTY_SET
 * @since 1.2
 */
public interface Set<E> extends Collection<E> {
    /**
     * @param e element to be added to this set
     * @return <tt>true</tt> if this set did not already contain the specified
     *         element
     * @throws UnsupportedOperationException if the <tt>add</tt> operation
     *         is not supported by this set
     * @throws ClassCastException if the class of the specified element
     *         prevents it from being added to this set
     * @throws NullPointerException if the specified element is null and this
     *         set does not permit null elements
     * @throws IllegalArgumentException if some property of the specified element
     *         prevents it from being added to this set
     */
    boolean add(E e);

     /**
     * @param o object to be removed from this set, if present
     * @return <tt>true</tt> if this set contained the specified element
     * @throws ClassCastException if the type of the specified element
     *         is incompatible with this set
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws NullPointerException if the specified element is null and this
     *         set does not permit null elements
     * (<a href="Collection.html#optional-restrictions">optional</a>)
     * @throws UnsupportedOperationException if the <tt>remove</tt> operation
     *         is not supported by this set
     */
    boolean remove(Object o);

    //other methods
}

I am not getting, why add method is taking E parameter and remove method is taking Object parameter as a input argument?

Any help or reference link to understand this behavior would be appreciate.

Vishal Zanzrukia
  • 4,902
  • 4
  • 38
  • 82
  • 2
    Duplicate of http://stackoverflow.com/questions/17138241/java-add-remove-methods-of-sets – Ray Jun 11 '15 at 13:10
  • 4
    possible duplicate of [Why aren't Java Collections remove methods generic?](http://stackoverflow.com/questions/104799/why-arent-java-collections-remove-methods-generic) – AdamSkywalker Jun 11 '15 at 13:13

4 Answers4

0

Because your Set will always return E, but you may want to check if an object (not necessarily E) is in the Set.

0

I agree, it's wierd, but it allows you to do the following:

Set<String> stringSet = new HashSet<String>();
stringSet.add("blah");

Object blah = "blah";
stringSet.remove(blah);
Karrde
  • 471
  • 2
  • 9
0

The add method of collections is 'covariant', which means that you can add any element of type E or of a subtype of E. The remove method however is contravariant, you can remove any object that is a either of type E or of a supertype of E. Normally, the syntax would have to be

public boolean remove(? super E element)

But since this syntax is not valid in Java (unfortunately), the type of the parameter is Object, which is always a super type of E, no matter what E is.

This also allows you to remove an object from the collection whose runtime type is E while its compile-time type is a supertype of E. For example, take a look at this simple piece of code

List<String> list = new ArrayList();
list.add("abc");

Object o = "abc";
list.remove(o);

This code shows that you should be able to remove any object from the collection that has the same or a supertype of the collection. Due to the syntactic limitation of Java, the method would also accept any other object that could never be in the collection due to its type:

list.remove(1);

This example compiles perfectly fine, but it makes no sense: You could never have an Integer in your List<String>.

Conclusion

The parameter type of remove is Object because it represents the supertype of all types, and it lets you remove an element that has been upcasted to Object while it could still be an element in the collection due to its runtime type. The signature remove(? super E) is neither possible nor necessary, but it would warn the programmer when an operation can never succeed, like remove(1) on a List<String>.

Clashsoft
  • 11,553
  • 5
  • 40
  • 79
  • where did you get this explanation? – AdamSkywalker Jun 11 '15 at 13:36
  • I don't have any actual source, but it's the most logical explanation. I will edit my answer to explain it. – Clashsoft Jun 11 '15 at 14:37
  • I understand your idea, but I think it is not true about supertypes. It is mostly about safetness and backward compatibility. – AdamSkywalker Jun 11 '15 at 14:40
  • Are you sure it couldn't be `public boolean remove(T element)`? – EpicPandaForce Jun 11 '15 at 14:45
  • Might be because of safety and backwards compatibility in Java, but the signature should be `remove(? super E)` in a world where this syntax is possible. That way, the compiler could warn you about `remove` operations that will always fail, like `stringList.remove(1)`. – Clashsoft Jun 11 '15 at 14:46
  • 1
    @EpicPandaForce unfortunately, this is also invalid syntax, but it represents the same thing as `remove(? super E)`. – Clashsoft Jun 11 '15 at 14:48
  • huh, it **is** invalid syntax. I guess you can only use `extends` in generic methods. Well, at least I learned something new. – EpicPandaForce Jun 11 '15 at 14:51
  • When writing a collection library, I also had to learn this the hard way while trying to write my `remove` methods. This is why I came up with the `remove(? super E)` in the first place. – Clashsoft Jun 11 '15 at 14:52
0

In public boolean add(E e) E means the the type of elements maintained by this set. You can only permitted element of type in collection. Inernally its maps at work

 public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }

In public boolean remove(Object o) Removes the specified element from this set if it is present. You dont need to check what type of element it is - just check if its there take it out.

again maps at work internally

 public boolean remove(Object o) {
        return map.remove(o)==PRESENT;
    }
Sheetal Mohan Sharma
  • 2,908
  • 1
  • 23
  • 24