Search code examples
javacollectionstreeset

Java TreeSet not adding object


I am trying to add objects into a Treeset but the objects not all are getting added.

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

From public static void main of another class.

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

The output I get is :

--Fruits Example--
Apple-1-3

But when I have fruits objs as below i get the all the objects just keeping everything same but the third element. Fruits f1= new Fruits("Apple",1,3); Fruits f2= new Fruits("Apple",1,1); Fruits f3= new Fruits("Apple",1,2);

The output get for this is

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

So somehow my objects are treated as same when I keep different elements on weight and price. I couldn't figure out as why the objects are treated as same. Please help.


Solution

  • The primary issue is, you are always checking two fields to be equal and only one to be different. At the final else, that happens if at least 2 fields are different, you return 0 which means they should be treated as equal, and that is the reason you have this issue.

    Since the order you want is to first sort by name, then by quantity and then by price, remove the && f1.price == f2.price from the 4th condition onwards, and remove && f1.weight==f2.weight on the last two.


    You can avoid this issue completely if you use Java 8 style.

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

    I have added the working code in codiva - online java compiler ide. I have also included a slightly cleaner implementation in FruitsComparator.java file.