为通用集合编写 contains()
我正在用java编写一个skiplist类作为练习。我编写了一个名为 SkipListInternal
的类,其中包含实际的跳过列表。我还创建了一个名为 SkipListSet
的包装类,它实现 SortedSet
接口并包含 SkipListInternal
的实例>。
除此之外,SkipListInternal
包含一个方法 E find(E e)
,该方法返回等于 e
的元素(如果存在),否则返回 null。
在编写 boolean contains(Object o)
(通过 SortedSet
从 Collection
继承)方法时,我注意到它的参数是一个对象而不是 E。我打算做这样的事情,但由于类型擦除而不可能:
public class SkipListSet<E> implements SortedSet<E>{
private SkipListInternal<E> skiplist;
...
public boolean contains(Object o){
if (!(o instanceof E)) return false;
return skiplist.find((E) o) != null;
}
...
}
既然不能这样做,我应该怎么做?
I'm writing a skiplist class in java as an excercise. I've written a class called SkipListInternal<E>
which contains the actual skiplist. I've also made a wrapper class called SkipListSet<E>
which implement the SortedSet<E>
interface and contains an instance of SkipListInternal<E>
.
Among other things, SkipListInternal<E>
contains a method E find(E e)
which returns the element equal to e
if it is present, and otherwise returns null.
When writing the boolean contains(Object o)
(inherited from Collection<E>
via SortedSet<E>
) method I noticed that its argument is an Object and not an E. I intended to do something like this, but is not possible due to type erasure:
public class SkipListSet<E> implements SortedSet<E>{
private SkipListInternal<E> skiplist;
...
public boolean contains(Object o){
if (!(o instanceof E)) return false;
return skiplist.find((E) o) != null;
}
...
}
Since it can't be done this way, how should I do it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
严格来说,这样的实现是错误的。
这样做的原因是,即使对象不是
E
类型,它仍然可以在equals()
调用上返回true
。假设您有一个像这样的类:
然后此代码将打印
true
:并且只是为了澄清:此行为是预期,并且是原因
contains()
采用Object
而不是E
。顺便说一句,remove()
也是如此。Strictly speaking such an implementation would be wrong.
The reason for this is that even if an object is not of type
E
, it could still returntrue
on anequals()
call.Assume for a second, that you've got a class like this:
Then this code would print
true
:And just to clarify: this behaviour is intended and is the reason why
contains()
takes anObject
instead ofE
. The same is true forremove()
, by the way.由于
contains()
来自java.util.Collection
,我们应该遵循Collection.contains()
contract< /强>。由于抛出ClassCastException
是一种可选行为,因此当转换失败时,在代码中返回 false 是正确的。所以我认为你的实施符合合同。Since the
contains()
is fromjava.util.Collection
, We are supposed to follow theCollection.contains()
contract. Because throwingClassCastException
is an optional behavior, it's correct to return false in your code when cast fails. So I think your implementation comply with the contract.@Joaschim 注释对于标准集合是正确的,但是如果您想要一个检查的集合,我建议您检查可以添加的内容,而不是针对无效类型的查找进行优化(除非您想抛出异常)您可以执行类似的操作。
顺便说一句:Java 有一个内置的线程安全
ConcurrentSkipListSet
和ConcurrentSkipListMap
您可能会发现阅读其源代码很有趣。 ;)@Joaschim comment is correct for standard collections, however if you want a checked collection I suggest you check what can be added, and not optimise for the lookups of invalid types (unless you want to throw an Exception) You can do something like.
BTW: Java has a builtin thread safe
ConcurrentSkipListSet
andConcurrentSkipListMap
You might find it interesting to read the source for this. ;)为了使排序集实现正常工作,集合中的元素必须具有顺序。这可以是“自然的”(即元素实现
Comparable
)或“强加的”(通过在集合构造期间使用显式的Comparator
)。因此,第一件事是,您可能更愿意使用为 set 元素定义的顺序(毕竟,您正在实现
SortedSet
!)而不是equals
contains
以提高效率。我假设您已经在内部SkipListInternal
中使用排序 - 您如何在给定的SortedSet
中维护Sorted
只有等于
吗?contains
实际上在接口中被声明为contains(Object key)
,这确实很不幸。我会做TreeMap
实现的作用(它是TreeSet
的底层容器,集合框架中的标准SortedSet
):即,强制转换,假设使用您的集合的客户端应用程序行为正常。
In order for a sorted set implementation to work, the elements of the set have to have an ordering. This may either be "natural" (i.e., the elements implement
Comparable
) or "imposed" (by using an explicitComparator
during set construction).So, the first thing is, that you'd probably rather use the ordering defined for the set elements (after all, you are implementing a
SortedSet
!) instead ofequals
incontains
for efficiency. I assume, that you are already using an ordering in your internalSkipListInternal<E>
-- how'd you maintain theSorted
inSortedSet
given onlyequals
?The fact that
contains
is actually declared ascontains(Object key)
in the interface is really unfortunate. I'd do, what theTreeMap
implementation does (which is the underlying container forTreeSet
, the standardSortedSet
from the collections framework):i.e., cast, assuming the client application using your collection behaves sanely.