omid gholami
omid gholami

Reputation: 97

Sorting and object by a parameter

I have a class with some String parameters. I made a list of instances from this object. Then I made a comparator sort function to sort the list by different topics. For example by StartTime or EndTime. The time is defined in String format. Here is the compare function for sort:

if (sortType == Sort.STARTTIME){
    Collections.sort(routeList, new Comparator<Route>() {
        @Override
        public int compare(Route o1, Route o2) {
            if (Double.parseDouble(o1.getTimeS()) >= (Double.parseDouble(o2.getTimeS())))
                return 1;
            else
                return -1;
        }
    });
}

It works but when I change the comparator with > or < or <= sign it will not work! or when I compare them with endTime , then only works with <= and I cannot sort it in an increasing order!!!! Even I cannot change the place ot 1 and -1.

if (sortType == Sort.ENDTIME){
    Collections.sort(routeList, new Comparator<Route>() {
    @Override
    public int compare(Route o1, Route o2) {
        if ((Double.parseDouble(o1.getTimeE()) <= Double.parseDouble(o2.getTimeE()))))
            return 1;
        else
            return -1;
    }
});
}

I really don't know what is the matter with it!!!!!!!

public class Route extends Arc {
    private  String type;
    private int secId;
    private String tId;
    private int event;
    private String name;
    private String nameS;
        }
    private String nameE;
    private String timeS;
    private String timeE;
    .....
}

And here are some lines of data

57779.999999999985 57779.999999999956 57778.999999999985 57778.99999999994 57778.99999999993 57778.99999999988 57777.0 57777.0 57750.0 57749.99999999994 57734.99999999994 57734.99999999988 57719.999999999985 57719.999999999985

Upvotes: 2

Views: 73

Answers (3)

Ernesto Campohermoso
Ernesto Campohermoso

Reputation: 7371

When use a comparator you implement the logic of comparison.

Then in the following code:

public int compare(Route o1, Route o2) {
        if (Double.parseDouble(o1.getTimeS()) >= (Double.parseDouble(o2.getTimeS())))
            return 1;
        else
            return -1;
    }

You are basically comparing doubles "Double.parseDouble". If you want compare strings you can use compareTo method as follows:

public int compare(Route o1, Route o2) {
        return o1.type1.compareTo(o2.type1);
}

Assuming that type1 attributes for o1 and o2 will never be null else you need to improve the code.

The point is: Inside compare method you must need provide the logic for compare two objects. Imagine that you have a class Student:

public class Student {
    public int id;
    public String name;
    public double score;
    public Student (int id, String name, double score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }
}

And two instances:

Student foo = new Student(100,"Foo", 10.5);
Student bar = new Student(50,"Bar", 90.5);

For sorting purposes which of following is true?:

foo > bar
bar > foo
foo == bar

Java doesn't know you must provide the logic:

if you wat to order by id:

public int compare(Student s1, Student s2) {
    return s1.id - s2.id;
}

if you wat to order by name:

public int compare(Student s1, Student s2) {
    return s1.name.compareTo(s2.name);
}

if you wat to order by score in descendent way:

public int compare(Student s1, Student s2) {
    return (s2.score  - s1.score) * 100; 
}

Upvotes: 0

GhostCat
GhostCat

Reputation: 140447

Your understanding of comparators is wrong.

They ought to return -1, 1, and 0 when things are equal. Thus you current comparison using <= and returning either -1 or 1 is incorrect.

Instead, you have to implement such logic that:

Compares its two arguments for order. Returns a negative integer, zero, or a positive integer as the first argument is less than, equal to, or greater than the second.

In other words: your first implementation probably worked for that data you tested with; but it is incorrect; and reversing the logic doesn't fix that problem.

Finally: the easy answer here; simply use Double.compare() within your comparator. As comparing floating point numbers is actually a tricky business.

Upvotes: 6

omid gholami
omid gholami

Reputation: 97

The right answer

public int compare(Route o1, Route o2) {
    if (Double.parseDouble(o1.getTimeS()) < (Double.parseDouble(o2.getTimeS())))
         return -1;
    else if (Double.parseDouble(o1.getTimeS()) == (Double.parseDouble(o2.getTimeS())))
        return 0;
    else
        return +1;
    }
});

Upvotes: 0

Related Questions