包含给出错误的结果

时间:2013-06-12 18:10:14

标签: java contains treeset

我有一个班级'CoAutoria',可以容纳2个“作者”类的实例(目前只有一个名字)以及这些作者的共同文章数量。
为了找出共同作者的前十名(关于文章数量),我创建了一个'CoAutoria'的TreeSet,用于保存每一对的文章总数。 我需要循环浏览多年的地图,收集不同的作者和他们各自的共同作者集。然后,为每对创建一个'CoAutoria'实例并:将其添加到树集中(如果它尚不存在);或者简单地将其文章数量与该集合中存在的文章数量相加。

我已经创建了compareTo方法,将其插入到树集上,并创建了equals方法,以便作者的顺序无关紧要。

这是主要代码:`

public class CoAutoria implements Comparable<CoAutoria>
{    
private Autor autor1;
private Autor autor2;
private int artigosComum;
(...) 
}


@Override
public int compareTo(CoAutoria a2)
{
    String thisAutor1 = autor1.getNome();
    String thisAutor2 = autor2.getNome();
    String caAutor1 = a2.getAutor1().getNome();
    String caAutor2 = a2.getAutor2().getNome();
    if((autor1.equals(a2.getAutor1()) && autor2.equals(a2.getAutor2())) || (autor1.equals(a2.getAutor2()) && autor2.equals(a2.getAutor1())))
    {
        return 0;
    }
    else
    {               

       return 1;
    }        
}    
@Override
public boolean equals(Object o)
{
    if(this == o)
    {
        return true;
    }


    if( o == null || o.getClass() != this.getClass())
        return false;

    CoAutoria ca  = (CoAutoria) o;
    String thisAutor1 = autor1.getNome();
    String thisAutor2 = autor2.getNome();
    String caAutor1 = ca.getAutor1().getNome();
    String caAutor2 = ca.getAutor2().getNome();
    if((thisAutor1.equals(caAutor1) && thisAutor2.equals(caAutor2)) || (thisAutor1.equals(caAutor2) && thisAutor2.equals(caAutor1)))
    {
        return true;
    }
    else
    {               
        return false;
    }

}

主要问题是:当我检查该集合是否已经具有某个'CoAutoria'实例时,(我正在使用TreeSet的contains()方法),它会给我错误的结果...有时它会正确检查对AB已经存在于该集合中(以BA的形式),但有时它不会...对于我所读到的,包含使用equals方法,因此不会发生这种情况。

[编辑:] 从第一篇文章开始,我开始认为问题可能存在于compareTo ..所以我将其改为

public int compareTo(CoAutoria a2)
{
String thisAutor1 = autor1.getNome();
String thisAutor2 = autor2.getNome();
String caAutor1 = a2.getAutor1().getNome();
String caAutor2 = a2.getAutor2().getNome();
if(this.equals(a2))
{
    System.out.println("return 0");
    return 0;
}
else
{               
   int aux = thisAutor1.compareTo(caAutor1);
   if(aux != 0)
   {
       return aux;

   }
   else
   {
       return thisAutor2.compareTo(caAutor2);

   }

}        

}

但它仍然给我糟糕的结果......我想我现在已经想到了:如果它是相同的'CoAutoria',我返回0,如果不是我通过名称,并按照他们的compareTo值排序..但缺少一些东西

1 个答案:

答案 0 :(得分:2)

您的contains方法正在中断,因为您的compareTo方法始终返回0或正数,没有负数。这意味着您的compareTo不一致。如果作者相同,则正确的实现应返回0;如果作者不同,则应返回正负值。

示例(假设author1author2不同):

 int i = author1.compareTo(author2); // i should be positive or negative
 int j = author2.compareTo(author1); // j should be the opposite of i

对于上述两种情况,您将返回1,这将使有序集合无效,因为任何元素都不会smaller。另一个例子想象一下,如果你有一个二元树(有序集合),它有元素[1-10]。如果您正在搜索元素5,那么在将5与任何元素进行比较时,您的二叉树总是会说它等于或大于。

你应该如何改变它取决于你。但是一个想法是按名称对作者进行排序,然后迭代两个集合并按字典顺序将作者进行比较。

编辑:即使您对方法进行了编辑,它们仍然不一致。尝试以下方法,它们不是最有效的,但除非您真的想要优化速度,否则应该有效。请注意,他们首先排序以确保author1和author2在与另一个CoAutor进行比较之前是有序的。我不做任何空检查,并假设两者都是有效的作者。

@Override
public boolean equals(Object o){
    if (o == null || !(o instanceof CoAutoria)) return false;
    if (o == this) return true;
    return this.compareTo((CoAutoria)o) == 0;
}

@Override
public int compareTo(CoAutoria o) {
    List<String> authors1 = Arrays.asList(autor1.getNome(), autor2.getNome());
    List<String> authors2 = Arrays.asList(o.autor1.getNome(), o.autor2.getNome());
    Collections.sort(authors1);
    Collections.sort(authors2);
    for (int i=0;i<authors1.size();i++){
        int compare = authors1.get(i).compareTo(authors2.get(i));
        if (compare != 0)
            return compare;
    }
    return 0;
}