6

可能重复:
Map.get(Object key) 不是(完全)通用的
原因是什么 Java 的 TreeSet<E> remove(Object) 不采用 E

为什么 HashSet 在这里不将参数类型限制为 E:

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

就像对 add() 所做的那样

public boolean add(E e)

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

4

4 回答 4

4

不同之处在于添加必须是类型安全的以保持集合的完整性,而项目检查/删除可以承受“类型宽容”而不会有损害集合类型安全的风险。换句话说,如果你添加了一个错误类型的元素,这个集合就会失效;另一方面,如果您检查是否存在错误类型的元素,您将简单地返回一个false. 同样适用remove:如果你传递一个不兼容类型的元素,它不会在集合+中,所以删除将是一个空操作。


+除非您通过利用类型擦除的 hack 将其放入。

于 2012-10-09T20:20:03.750 回答
2

那么该集合不能包含/删除任何其他类型

当然可以。阅读类型擦除或将您的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]

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

于 2012-10-09T20:19:07.160 回答
2

contains和的参数remove不能被限制,E因为你应该能够给它们相等的对象,这非常有用。更准确地说,APIHashSet.remove说:

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

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

因此,为了启用containsand的更一般的功能remove(在等价类上,而不仅仅是对象身份),它们必须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: [[]]
于 2012-10-09T21:00:13.113 回答
0

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

于 2012-10-09T20:19:18.157 回答