Java TreeSet不添加对象

时间:2016-06-22 17:56:55

标签: java collections treeset

我正在尝试将对象添加到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;
    }       
}

来自另一个类的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

但是当我得到如下水果的时候,我得到了所有的物品 只保持一切,但第三个元素。      水果f1 =新水果(&#34; Apple&#34; 1,3);         水果f2 =新水果(&#34; Apple&#34; 1,1);         水果f3 =新水果(&#34; Apple&#34;,1,2);

输出get为

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

因此,当我在重量和价格上保持不同的元素时,我的对象被视为相同。我无法弄清楚对象被视为同样的原因。请帮忙。

4 个答案:

答案 0 :(得分:1)

树相关系列不使用equals()hashCode()。这些对Map发挥作用。

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

首先Apple进入,因为树是空的。第二&amp;在所有false条件中,第3个Apple结果为if,从而返回最终0。在最终System.out.println()之前加return进行确认。

如果你想先按名称对水果进行分类,那么按重量计算&然后最终按价格,这是一个更紧凑的方式:

@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);
    }
}

答案 1 :(得分:1)

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

由于您要的订单首先按名称排序,然后按数量排序,然后按价格排序,从第4个条件开始删除&& f1.price == f2.price,然后删除最后两个的&& f1.weight==f2.weight

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

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

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

答案 2 :(得分:0)

您在课程equals中的Fruits方法出错:

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)

(注意最后一部分)。

答案 3 :(得分:0)

TreeSet,当与Comparator一起使用时,元素的相等性由compare的{​​{1}}方法决定,否则将使用Comparator其元素的方法,因为它们需要实现compareTo接口。 Comparablehashcode方法仅由equals接口本身使用(例如方法Set使用contains方法检查元素是否已呈现) 。在equals使用hashcode时,TreeSet不是HashSet使用的,这是实现Set接口的另一种方式。因此,在您的代码中,由于您compare覆盖的Comparator方法将这些元素视为相等,因此无法多次插入它们。 Java Tutorial指出的一个指导原则是,compare方法应符合equals方法,即compare方法中的元素应该被视为相等,当且仅当equals方法。

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

供您参考,请参阅Java Object Ordering教程,以及两天前我提出的a question