Treeset.contains()问题 [英] Treeset.contains() problem

查看:241
本文介绍了Treeset.contains()问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我现在一直在努力解决问题,我想在这里也可以寻求帮助。

So I've been struggling with a problem for a while now, figured I might as well ask for help here.

我将Ticket对象添加到一个TreeSet,Ticket实现了Comparable并重写了equals(),hashCode()和CompareTo()方法。我需要使用contains()检查对象是否已经在TreeSet中。现在在向集合中添加2个元素后,它们都检查得很好,但是在添加第三个元素之后它就搞砸了。

I'm adding Ticket objects to a TreeSet, Ticket implements Comparable and has overridden equals(), hashCode() and CompareTo() methods. I need to check if an object is already in the TreeSet using contains(). Now after adding 2 elements to the set it all checks out fine, yet after adding a third it gets messed up.

在添加第三个元素之后运行这一小段代码对于TreeSet,Ticket temp2是我正在检查的对象(verkoopLijst)。

running this little piece of code after adding a third element to the TreeSet, Ticket temp2 is the object I'm checking for(verkoopLijst).

    Ticket temp2 = new Ticket(boeking, TicketType.STANDAARD, 1,1);
    System.out.println(verkoop.getVerkoopLijst().first().hashCode());
    System.out.println(temp2.hashCode());

    System.out.println(verkoop.getVerkoopLijst().first().equals(temp2));
    System.out.println(verkoop.getVerkoopLijst().first().compareTo(temp2));
    System.out.println(verkoop.getVerkoopLijst().contains(temp2));

返回:

22106622
22106622
true
0
false

现在我的问题是如何做到这一点?

Now my question would be how this is even possible?

编辑:

public class Ticket implements Comparable{

    private int rijNr, stoelNr;
    private TicketType ticketType;
    private Boeking boeking;


    public Ticket(Boeking boeking, TicketType ticketType, int rijNr, int stoelNr){    
        //setters
    }

    @Override
    public int hashCode(){
        return boeking.getBoekingDatum().hashCode();     
    }

    @Override
    @SuppressWarnings("EqualsWhichDoesntCheckParameterClass")    
    public boolean equals(Object o){
       Ticket t = (Ticket) o;

       if(this.boeking.equals(t.getBoeking())
               &&
          this.rijNr == t.getRijNr() &&  this.stoelNr == t.getStoelNr()
               &&
          this.ticketType.equals(t.getTicketType()))
       {
           return true;
       }

       else return false;

    }

    /*I adjusted compareTo this way because I need to make sure there are no duplicate Tickets in my treeset. Treeset seems to call CompareTo() to check for equality before adding an object to the set, instead of equals().


     */
    @Override
    public int compareTo(Object o) {
        int output = 0;
        if (boeking.compareTo(((Ticket) o).getBoeking())==0)
        {
            if(this.equals(o))
            {
                return output;
            }
            else return 1;
        }
        else output = boeking.compareTo(((Ticket) o).getBoeking());
        return output;
    }

    //Getters & Setters


推荐答案

On compareTo 合约



问题在于你的 compareTo 。以下是文档的摘录:

On compareTo contract

The problem is in your compareTo. Here's an excerpt from the documentation:


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

您的原始代码转载于此处供参考:

Your original code is reproduced here for reference:

// original compareTo implementation with bug marked

@Override
public int compareTo(Object o) {
    int output = 0;
    if (boeking.compareTo(((Ticket) o).getBoeking())==0)
    {
        if(this.equals(o))
        {
            return output;
        }
        else return 1; // BUG!!!! See explanation below!
    }
    else output = boeking.compareTo(((Ticket) o).getBoeking());
    return output;
}

为什么返回1; 一个错误?请考虑以下情形:

Why is the return 1; a bug? Consider the following scenario:


  • 给定票证t1,t2

  • 给定 t1.boeking.compareTo(t2.boeking)== 0

  • 给定 t1.equals(t2) return false

  • 现在我们有以下两种情况:


    • t1.compareTo(t2)返回 1

    • t2.compareTo(t1)返回 1

    • Given Ticket t1, t2
    • Given t1.boeking.compareTo(t2.boeking) == 0
    • Given t1.equals(t2) return false
    • Now we have both of the following:
      • t1.compareTo(t2) returns 1
      • t2.compareTo(t1) returns 1

      最后一个结果是 违规 compareTo 合约。

      That last consequence is a violation of the compareTo contract.

      首先,您应该利用 Comparable< T> 是可参数化的泛型类型的事实。也就是说,而不是:

      First and foremost, you should have taken advantage of the fact that Comparable<T> is a parameterizable generic type. That is, instead of:

      // original declaration; uses raw type!
      public class Ticket implements Comparable
      

      更适合宣布像这个:

      // improved declaration! uses parameterized Comparable<T>
      public class Ticket implements Comparable<Ticket>
      

      现在我们可以编写 compareTo(Ticket)(不再 compareTo(Object))。有很多方法可以重写这个,但这里有一个相当简单的方法:

      Now we can write our compareTo(Ticket) (no longer compareTo(Object)). There are many ways to rewrite this, but here's a rather simplistic one that works:

      @Override public int compareTo(Ticket t) {
         int v;
      
         v = this.boeking.compareTo(t.boeking);
         if (v != 0) return v;
      
         v = compareInt(this.rijNr, t.rijNr);
         if (v != 0) return v;
      
         v = compareInt(this.stoelNr, t.stoelNr);
         if (v != 0) return v;
      
         v = compareInt(this.ticketType, t.ticketType);
         if (v != 0) return v;
      
         return 0;
      }
      private static int compareInt(int i1, int i2) {
         if (i1 < i2) {
           return -1;
         } else if (i1 > i2) {
           return +1;
         } else {
           return 0;
         }
      }
      

      现在我们还可以定义等于(对象) compareTo(Ticket)而不是相反:

      Now we can also define equals(Object) in terms of compareTo(Ticket) instead of the other way around:

      @Override public boolean equals(Object o) {
         return (o instanceof Ticket) && (this.compareTo((Ticket) o) == 0);
      }
      

      注意 compareTo :它有多个 return 语句,但事实上,逻辑流程非常易读。另请注意排序标准的优先级是如何明确的,并且如果您有不同的优先级,则可以轻松重新排序。

      Note the structure of the compareTo: it has multiple return statements, but in fact, the flow of logic is quite readable. Note also how the priority of the sorting criteria is explicit, and easily reorderable should you have different priorities in mind.

      • What is a raw type and why shouldn't we use it?
      • How to sort an array or ArrayList ASC first by x and then by y?
      • Should a function have only one return statement?

      这篇关于Treeset.contains()问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆