为什么HashSet <e>不会在contains()和remove()</e>中将参数类型限制为E.

时间:2012-10-09 20:16:07

标签: java

  

可能重复:
  What are the reasons why Map.get(Object key) is not (fully) generic
  Why does Java's TreeSet<E> remove(Object) not take an E

为什么HashSet不限制E的参数类型:

public boolean contains(Object o)
public boolean remove(Object o)

就像添加()

一样
public boolean add(E e)

我的意思是如果编译器强制只添加E类型的对象,那么该集合不能包含/删除任何其他类型

4 个答案:

答案 0 :(得分:4)

不同之处在于添加必须是类型安全的,以保持集合的完整性,而项目检查/删除可以提供“类型宽容”,而不会有损害集合类型安全性的风险。换句话说,如果添加错误类型的元素,该集将变为无效;另一方面,如果您检查是否存在错误类型的元素,您只需返回false。同样适用于remove:如果传递一个不兼容类型的元素,它将不会出现在集合 + 中,因此删除将是一个无操作。

<小时/> + 除非你通过一个利用类型擦除的黑客入侵它。

答案 1 :(得分:2)

  

然后该集不能包含/删除任何其他类型

当然可以。阅读type erasure或将HashSet<E>投射到非通用HashSet,并添加一个非E类型的对象。

查看此代码:

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]

这种奇怪的原因是泛型类型的信息在运行时被删除,而你的集合变成了一组简单的对象。

答案 2 :(得分:2)

containsremove的参数不能仅限于E,因为您应该能够为它们提供相同的对象,这非常有用。更准确地说,HashSet.remove的API说:

  

...更正式地,删除一个元素e(o == null?e == null:   o.equals(e)),如果这个集合包含这样的元素。

Object.equalsObject作为参数,这对于启用不同类型之间的相等也非常有用。

因此,要启用containsremove的更一般功能(在等价类而不是仅对象标识上),他们必须将Object作为参数。


示例:

    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: [[]]

答案 3 :(得分:0)

您没有使用这两种方法向集合中添加任何内容,因此不需要约束type参数。如果类型不匹配,则方法只能返回false。