2009-10-21 54 views
2

我正在执行List实施。正因为如此,我必须覆盖的方法如何避免重写集合的方法中未经检查的强制转换?

Collection.containsAll(Collection<?> c); 
Collection.removeAll(Collection<?> c); 
Collection.retainAll(Collection<?> c); 

但是因为它是解释by Sun,他们接受与收藏任何类型的内容(注意<?>)。所以这个集合不会被编译器检查,而是由我自己来检查它。但怎么做呢?由于类型擦除,每个元素上的instanceof将不起作用。下一个解决方案是将每个元素都投射到ClassCastException。看这里:

public boolean containsAll(Collection<?> c) { 
    boolean foundAll = true; 
    for (Object element : c) { 
     try { 
      foundAll &= this.contains((T) element); 
     } catch (ClassCastException e) { 
      foundAll = false; 
     } 
    } 
    return foundAll; 
} 

其他两种方法看起来相似。这样可行。但它给了我编译器警告“警告:[unchecked] unchecked cast”!除非我用“@SuppressWarnings("unchecked")”来压制它,否则它将无法正常编译。

我不想依靠“@SuppressWarnings("unchecked")”,除非我真的必须。有没有办法避免它?你将如何实现像containsAll(Collection<?> c)那样的方法?

编辑

好了,对不起你们,我不太清楚。我不扩展AbstractList,我不想。我的列表是通过一个平衡的二叉树实现的。我有自己的执行insert(),remove(),(实际上是搜索叶)等,并且都采用(通用)类型的参数T。关键目标是拥有一个可以在迭代时修改的排序列表。

那么...我如何避免containsAll(Collection <?>)的警告?我必须投!

谢谢! craesh

+2

btw:只要foundAll是假的,你应该从你的循环中突破,否则你会做不必要的工作。实际上,你可以完全摆脱布尔标志。 – 2009-10-21 12:15:09

+0

哇,我从来没见过&=操作符。谢谢! – 2009-10-21 12:54:07

+0

@Joachim:谢谢,这是一个好主意! @matt:我很少使用它,但有时它非常有用;) – craesh 2009-10-21 13:41:56

回答

9

你不需要当你调用,因为它被定义为boolean contains(Object o)你的元素转换为T。请注意,您可以询问Collection<String>是否和Integer对象。没有必要的铸造。

remove()也需要Object,所以根本不需要铸造。

并顺便说一句:扩展AbstractList带走了实施List的大部分无聊工作。

+0

对AbstractList提示+1,我倾向于忘记那一个 – Abel 2009-10-21 12:15:11

+0

对不起,我的错:我简化了这个例子太多了。在这种情况下,元素将在contains()中被铸造。我有一个包含(T元素)的方法,我称这一个,但没有发布它。 – craesh 2009-10-21 13:38:50

+0

@craesh:你也可以提供这些,但如果你实现'List'接口,那么你可以简单地调用这些方法的非通用版本。 – 2009-10-21 14:03:41

2

只是为了澄清一个误解仿制药:每个元素

的instanceof不会因为类型擦除工作。

不,这是不正确的。 instanceof工作得很好。 “类型删除”意味着你无法获得编译时间类型,该类型是通过泛型为泛型声明的 - 但是你不关心这一点。

你想要检查的是你正在获取的元素的运行时类型。这是通过instanceof完成的,完全独立于泛型,并且可以工作。

当然,作为约阿希姆·绍尔指出的那样,你甚至不需要检查的类型在这个特定的情况下,这样的点是没有实际意义呢?

编辑:

由于事实上,Java的AbstractCollection就是这样的:

public boolean containsAll(Collection<?> c) { 
    Iterator<?> e = c.iterator(); 
    while (e.hasNext()) 
    if(!contains(e.next())) 
     return false; 
    return true; 
} 

(来自Sun的JDK源代码)。

那么你真的应该尝试从AbstractList或至少AbstractCollections

0
当然可以的

延伸AbstractList为了得到这些方法无继承,但你也可以遍历this,而不是c

@Override 
public boolean containsAll(Collection<?> c) { 
    Iterator<T> it = this.iterator(); 

    while (it.hasNext()) { 
     if (!c.contains(it.next())) { 
      return false; 
     } 
    } 

    return true; 
} 

或者干脆:

@Override 
public boolean containsAll(Collection<?> c) { 
    for (Object o : this) { 
     if (!c.contains(o)) { 
      return false; 
     } 
    } 

    return true; 
} 
+0

谢谢,但在我的情况下,这是没有选择。我的应用程序中我的列表可能包含多达10k个元素。我有一个二进制搜索,所以在我的列表中搜索比在迭代中搜索更快。 – craesh 2009-10-21 14:23:27

0

如果你不想扩展AbstractList,至少扩展AbstractCollection。那么你根本不需要实现这个方法,问题是没有意义的。

相关问题