【问题标题】:Why doesn't TreeSet compare all elements before adding a new element?为什么 TreeSet 在添加新元素之前不比较所有元素?
【发布时间】:2019-08-27 04:43:04
【问题描述】:

我尝试编写一个程序来存储不相等的对对象,由 2 个字符串组成。就此而言,对 (john, bob) 被认为等于 (bob, john)。我的 equals 和 compareTo 实现应该可以正常工作。为了检查有什么问题,我让我的程序输出为我尝试添加的每个新对所做的比较。看起来像这样:

@Override
public boolean equals(Object o){
    if (o==null){
        return false;
    }
    final Pair other = (Pair) o;
    return (this.compareTo(other)==0);
}



@Override
public int compareTo (Pair o){
  if (this.first.equals(o.first)){
      if (this.second.equals(o.second)){
          System.out.println("equal: "+this.first+" "+this.second+" and  " + o.first+" "+o.second);
          return 0;
      }
  }
  else if (this.first.equals(o.second)){
        if (this.second.equals(o.first)){
            System.out.println("equal: "+this.first+" "+this.second+" and  " + o.first+" "+o.second);
            return 0;
        }
  }
    System.out.println(" not equal " +this.first+" "+this.second+" and  " + o.first+" "+o.second);
  return -1;

示例输入:

 bob john
 john john
 john john
 john bob
 bob will
 john hohn

如果我让它运行,它将在每次试验后打印出 TreeSat 的大小以添加新元素。它还将打印 compareTo 方法中写入的内容。我添加了 cmets 来说明我的问题。

   equal: bob john and  bob john    //Why comparing the first element at  
                                      all?
1
 not equal john john and  bob john
2
 not equal john john and  bob john
equal: john john and  john john
2
equal: john bob and  bob john
2
 not equal bob will and  bob john
 not equal bob will and  john john
3

 not equal john hohn and  john john    //no comparision of (john hohn) and                                       
 not equal john hohn and  bob will     //(bob john) why?
4

【问题讨论】:

  • 这就是基于树的结构的优势——您实际上不必访问每个元素来执行某些操作。多亏了这一点,您可以达到次线性(具体来说,是对数)复杂度。
  • 你永远不会在你的compareTo 中返回1,这意味着传递给它的对象是相等或更小的,但永远不会更大
  • @Eugene 如果你要插入 BST,你肯定不需要比较集合的所有元素来找到它的正确位置,对吗?
  • TreeSet 已排序,您无法将其关闭。您为它提供了一个无法正常进行排序的 compareTo,因此引用 API 文档“它只是不遵守 Set 接口的一般合同”。
  • HashSet 通常不会比较所有内容,如果你有一个好的 hashCode(没有冲突),它应该只做一个比较。冲突是两个或多个不相等的元素共享相同的 hashCode 值,然后由相等区分。

标签: java equals hashset treeset


【解决方案1】:

一个: 回答您的问题:TreeSet 不需要比较所有元素,因为元素有定义的顺序。考虑一本字典:在中间打开它,你会立即知道,你需要的单词是在那一页之前还是之后。您不需要检查字典的两半。

两个: 您的 compareTo() 方法有问题。考虑两个对象:

Pair a = Pair.of(1, 2);
Pair b = Pair.of(3, 4);

您的 compareTo() 在这两种情况下都将返回 -1,但它不能:

a.compareTo(b) == -1
b.compareTo(a) == -1

从数学上讲,您的关系“compareTo”没有定义顺序,因此违反了API 合约:

实施者必须确保所有 x 和 y 的 sgn(x.compareTo(y)) == -sgn(y.compareTo(x))。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-30
    • 2014-04-03
    • 1970-01-01
    • 1970-01-01
    • 2019-01-08
    • 1970-01-01
    相关资源
    最近更新 更多