Java TreeSet 未添加对象

Java TreeSet not adding object

我正在尝试将对象添加到 Treeset 中,但并非所有对象都被添加。

class Fruits
{
     String name ;
     int weight;
     int price;

    Fruits(String n, int w, int p)
    { 
        this.name=n;
        this.weight=w;
        this.price =p;
    }

    @Override
    public int hashCode() {
        System.out.println("hashcode called");
        int prime =31;
        int result =1;
        result = prime*result +(this.name.hashCode()+this.price+this.weight);
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        System.out.println("Equals called");
        if(null!=obj)
        {
            Fruits f= (Fruits) obj;
            if(this.name.equals(f.name) && this.price==f.price && this.weight == f.price)
            {
                return true;
            }
        }
        return false;
    }
}

class FruitsComparator implements Comparator<Fruits>
{
    //Order by Name, then quanity and then Price
    @Override
    public int compare(Fruits f1, Fruits f2)
    {
        if(f1.name.equals(f2.name) && f1.weight == f2.weight && f1.price == f2.price)
        {
            System.out.println(1);
            return 0;
        }
        else if(f1.name.equals(f2.name) && f1.weight==f2.weight && f1.price < f2.price)
        {
            System.out.println(2);
            return -1;
        }
        else if (f1.name.equals(f2.name) && f1.weight==f2.weight && f1.price > f2.price)
        {
            System.out.println(3);
            return 1;
        }
        else if (f1.name.equals(f2.name) && f1.weight<f2.weight && f1.price == f2.price)
        {
            System.out.println(4);
            return -1;
        }
        else if (f1.name.equals(f2.name) && f1.weight>f2.weight && f1.price == f2.price)
        {
            System.out.println(5);
            return 1;
        }
        else if (f1.name.compareTo(f2.name) <1 && f1.weight==f2.weight && f1.price == f2.price)
        {
            System.out.println(6);
            return -1;
        }
        else if (f1.name.compareTo(f2.name) >1 && f1.weight==f2.weight && f1.price == f2.price)
        {
            System.out.println(7);
            return 1;
        }
            return 0;
    }       
}

来自另一个 class 的 public static void main。

Fruits f1= new Fruits("Apple",1,3);
Fruits f2= new Fruits("Apple",10,1);
Fruits f3= new Fruits("Apple",15,2);
Set<Fruits> sf = new TreeSet<Fruits>(new FruitsComparator());
sf.add(f1);
sf.add(f2);
sf.add(f3);
System.out.println("--Fruits Example--");
for( Fruits f: sf)
{
    System.out.println(f.name+"-"+f.weight+"-"+f.price);
}

我得到的输出是:

--Fruits Example--
Apple-1-3

但是当我有下面的水果对象时,我得到了所有的对象 除了第三个元素之外,一切都保持不变。 Fruits f1= new Fruits("Apple",1,3); Fruits f2= new Fruits("Apple",1,1); 水果 f3= 新水果 ("Apple",1,2);

得到的输出是

--Fruits Example--
Apple-1-1
Apple-1-2
Apple-1-3

因此,当我在重量和价格上保留不同的元素时,我的物品会以某种方式被视为相同。我无法弄清楚为什么对象被视为相同。请帮忙。

您在 class Fruits 中的 equals 方法有错误:

if(this.name.equals(f.name) && this.price==f.price && this.weight == f.price)

应该是:

if(this.name.equals(f.name) && this.price==f.price && this.weight == f.weight)

(注意最后一部分)。

树相关的集合不使用 equals()hashCode()Map.

您在 compare 中的条件导致 0,因此未插入水果。

第一个苹果进去,因为树是空的。第 2 个和第 3 个苹果在所有 if 条件下的结果为 false,从而返回最终的 0。在最后的 return 前放一个 System.out.println() 来确认。

如果您想先按名称对水果进行排序,然后按重量排序,最后按价格排序,这里有一个更简洁的方法:

@Override
public int compare(Fruits f1, Fruits f2) {
    if (f1.name.equals(f2.name)) {
        if (f1.weight < f2.weight) {
            return -1;
        } else if (f1.weight > f2.weight) {
            return 1;
        } else {
            if (f1.price < f2.price) {
                return -1;
            } else if (f1.price > f2.price) {
                return 1;
            } else {
                return 0;
            }
        }
    } else {
        return f1.name.compareTo(f2.name);
    }
}

TreeSet,与Comparator一起使用时,元素是否相等由Comparatorcompare方法决定,否则使用[=14] =] 方法,因为它们需要实现 Comparable 接口。 hashcodeequals 方法只会被 Set 接口本身使用(例如方法 contains 使用 equals 方法来检查元素是否被呈现) . hashcode 不是 TreeSet 使用的东西,而 HashSet 使用它,这完全是实现 Set 接口的另一种方式。因此,在您的代码中,由于您重写了 Comparatorcompare 方法将这些元素平等对待,因此它们不能被多次插入。 Java 教程指出的一个准则是,compare 方法应符合 equals 方法,也就是说,元素在 compare 方法中应被平等对待,如果并且仅当 equals 方法执行时。

并且在您的 equals 方法中,您确实使用了 this.weight == f.price 来比较两个水果,我认为这不是您打算做的。这使得您的 equals 方法与 compare 方法不一致。

参考一下Java Object Ordering tutorial, and as well as 我前两天问过

主要问题是,您总是检查两个字段是否相等,只有一个字段不同。 在最后,如果至少有 2 个字段不同,就会发生这种情况,你 return 0 这意味着它们应该被视为相等,这就是你遇到这个问题的原因。

由于你要的顺序是先按名称排序,再按数量排序,再按价格排序,从第4个条件开始去掉&& f1.price == f2.price,去掉后两个的&& f1.weight==f2.weight


如果使用 Java8 样式,则可以完全避免此问题。

Set<Fruits> sf = new TreeSet<Fruits>(Comparator.comparing(Fruits::getName)
    .thenComparing(Fruits::getWeight)
    .thenComparing(Fruits::getPrice)
    );

我已经在 codiva - online java compiler ide 中添加了工作代码。我还在 FruitsComparator.java 文件中包含了一个稍微简洁的实现。