为什么Set.contains()似乎没有使用o.equals()?(Why does Set.contains() not seem to be using o.equals()?)

编程入门 行业动态 更新时间:2024-10-22 11:31:54
为什么Set.contains()似乎没有使用o.equals()?(Why does Set.contains() not seem to be using o.equals()?)

我有一个包含包装器的TreeSet,它将Foo对象存储在某个position ,定义如下:

class Wrapper implements Comparable<Wrapper> { private final Foo foo; private final Double position; ... @Override boolean equals(Object o) { ... if(o instanceof Wrapper) return o.getFoo().equals(this.foo); if(o instanceof Foo) return o.equals(this.foo); } @Override public int compareTo(MarkerWithPosition o) { return position.compareTo(o.getPosition()); } } NavigableSet<Wrapper> fooWrappers = new TreeSet<Wrapper>();

因为我希望我的TreeSet按position排序,但可以通过foo搜索。 但是当我执行这些操作时:

Foo foo = new Foo(bar); Wrapper fooWrapper = new Wrapper(foo, 1.0); fooWrappers.add(fooWrapper); fooWrapper.equals(new Wrapper(new Foo(bar), 1.0)); fooWrapper.equals(new Foo(bar)); fooWrappers.contains(fooWrapper); fooWrappers.contains(new Wrapper(foo, 1.0)); fooWrappers.contains(new Wrapper(new Foo(bar), 1.0)); fooWrappers.contains(new Wrapper(foo, 2.0)); fooWrappers.contains(foo);

我明白了:

true true true true true false Exception in thread "main" java.lang.ClassCastException: org.gridqtl.Marker cannot be cast to java.lang.Comparable at java.util.TreeMap.getEntry(TreeMap.java:325) at java.util.TreeMap.containsKey(TreeMap.java:209) at java.util.TreeSet.contains(TreeSet.java:217)

当我期望它们全部返回true ,似乎TreeSet.contains没有使用我的equals方法,因为API 建议 。 我需要覆盖另一种方法吗?

I have a TreeSet containing wrappers which store a Foo object at a certain position, defined like so:

class Wrapper implements Comparable<Wrapper> { private final Foo foo; private final Double position; ... @Override boolean equals(Object o) { ... if(o instanceof Wrapper) return o.getFoo().equals(this.foo); if(o instanceof Foo) return o.equals(this.foo); } @Override public int compareTo(MarkerWithPosition o) { return position.compareTo(o.getPosition()); } } NavigableSet<Wrapper> fooWrappers = new TreeSet<Wrapper>();

because I want my TreeSet to be ordered by position but searchable by foo. But when I perform these operations:

Foo foo = new Foo(bar); Wrapper fooWrapper = new Wrapper(foo, 1.0); fooWrappers.add(fooWrapper); fooWrapper.equals(new Wrapper(new Foo(bar), 1.0)); fooWrapper.equals(new Foo(bar)); fooWrappers.contains(fooWrapper); fooWrappers.contains(new Wrapper(foo, 1.0)); fooWrappers.contains(new Wrapper(new Foo(bar), 1.0)); fooWrappers.contains(new Wrapper(foo, 2.0)); fooWrappers.contains(foo);

I get:

true true true true true false Exception in thread "main" java.lang.ClassCastException: org.gridqtl.Marker cannot be cast to java.lang.Comparable at java.util.TreeMap.getEntry(TreeMap.java:325) at java.util.TreeMap.containsKey(TreeMap.java:209) at java.util.TreeSet.contains(TreeSet.java:217)

when I expecting them all to return true, so it seems like TreeSet.contains is not using my equals method as the API suggests. Is there another method I need to overwrite?

最满意答案

TreeSet是一个确实使用compareTo的Set实现,正如javadoc - emphasis mine中所解释的那样:

请注意,如果要正确实现Set接口,则由set维护的排序(无论是否提供显式比较器)必须与equals一致。 (请参阅Comparable或Comparator以获得与equals一致的精确定义。)这是因为Set接口是根据equals操作定义的,但TreeSet实例使用compareTo(或compare)方法执行所有元素比较 ,因此从该集合的角度来看,通过这种方法被认为相等的元素是相等的 。 集合的行为即使其排序与equals不一致也是明确定义的; 它只是不遵守Set接口的一般合同。

TreeSet is a Set implementation that does indeed use compareTo, as explained in the javadoc - emphasis mine:

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

更多推荐

本文发布于:2023-04-28 02:37:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1329789.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:Set   equals

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!