2

I know this seems to be a trivial question (and I have no doubt all the 'smart guys' would come and mark it as duplicate), but I havn't found any sufficient explanation to my question. Is it just me getting so much trouble to understand this simple subject?

I understand the basics behind Comparableinterface and how it works, but I have a truly difficulty to undestand HOW to determine the ORDER of the sort.

For example - I have this very simple Fruit class:

public class Fruit implements Comparable<Fruit> {
private String fruitName;
private String fruitDesc;
private int quantity;

public Fruit(String fruitName, String fruitDesc, int quantity) {
    this.fruitName = fruitName;
    this.fruitDesc = fruitDesc;
    this.quantity = quantity;
}

public String getFruitName() {
    return fruitName;
}
public void setFruitName(String fruitName) {
    this.fruitName = fruitName;
}
public String getFruitDesc() {
    return fruitDesc;
}
public void setFruitDesc(String fruitDesc) {
    this.fruitDesc = fruitDesc;
}
public int getQuantity() {
    return quantity;
}
public void setQuantity(int quantity) {
    this.quantity = quantity;
}

public int compareTo(Fruit compareFruit) {
    //ascending order
    return this.quantity - ((Fruit) compareFruit).getQuantity();
}

Why when declaring the compareTo like above it will sort by ascending order and when declaring it the opposite:

return ((Fruit) compareFruit).getQuantity() - this.quantity;

it will be by descending order?

Nimrod
  • 1,100
  • 1
  • 11
  • 27
  • What do you mean by "How do you determine between them?"? Do you mean how fruits are ordered with the same quantity? This will basically depend on the sort algorithm used. But you should not make any assumptions of the order of these elements as it might change unnoticed. If you depend on an exact and stable order you will need to ensure that all attributes of your class are considered for the sort order. – dpr Jun 28 '16 at 07:39
  • Not sure if I understand your question correctly - the sort order is simply determined by the sign of the integer returned by `compareTo`. By the way, don't mix attribute access via getter and direct attribute access. – Frank Puffer Jun 28 '16 at 07:39
  • When you swap the order of what is considered greater than or less than, you swap from ascending to descending. – Peter Lawrey Jun 28 '16 at 07:39
  • Fruit.compareTo define default behavior. For customization implement Comparator. – Sergey Morozov Jun 28 '16 at 07:39
  • It's not clear what you are asking which is not covered in the documentation. – Peter Lawrey Jun 28 '16 at 07:40
  • compareTo does not define asc/desc sorting. Sorting is done by the class that sorts Comparable implementations. compareTo must be implemented as in javadoc https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html#method_detail "Returns: a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object." so in your case current quantity - o.getQuantity would be correct – cxubrix Jun 28 '16 at 07:48
  • Sorry if I wasn't clear. I deleted the sentence 'How do you determine between them?'. I just meant that I don't understand why in the 1st example it orders by ascending order and on the 2nd example when I swap the order it orders by descending order. I know it return an INT (1, 0 or -1) - but I don't get it how when I write a programm can know the sorting order? why on the 1st example it actually ascending order? hope know it's clear. – Nimrod Jun 28 '16 at 07:49
  • @Nimrod in your example there is no sorting code. – cxubrix Jun 28 '16 at 08:03
  • @PeterLawrey - I understand what you meant about when swapping the order between greater & less. so if I want to conclude - when I'm writing this.object - theComparedObject I will always get it by ascending order? if not - is there any rule of thumb? – Nimrod Jun 28 '16 at 12:19

5 Answers5

2

From Javadoc

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object. The implementor must ensure sgn(x.compareTo(y)) == -sgn(y.compareTo(x)) for all x and y. (This implies that x.compareTo(y) must throw an exception iff y.compareTo(x) throws an exception.)

The implementor must also ensure that the relation is transitive: (x.compareTo(y)>0 && y.compareTo(z)>0) implies x.compareTo(z)>0.

Finally, the implementor must ensure that x.compareTo(y)==0 implies that sgn(x.compareTo(z)) == sgn(y.compareTo(z)), for all z.

It is strongly recommended, but not strictly required that (x.compareTo(y)==0) == (x.equals(y)). Generally speaking, any class that implements the Comparable interface and violates this condition should clearly indicate this fact. The recommended language is "Note: this class has a natural ordering that is inconsistent with equals."

In the foregoing description, the notation sgn(expression) designates the mathematical signum function, which is defined to return one of -1, 0, or 1 according to whether the value of expression is negative, zero or positive.

sidgate
  • 14,650
  • 11
  • 68
  • 119
1

The sort method is sorting on ascending order by its definition .

Sorts the specified list into ascending order, according to the natural ordering of its elements.

The compareTo method is right in your first example, wrong in the second, according to :

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

Arnaud
  • 17,229
  • 3
  • 31
  • 44
  • Why is it wrong? I checked it and it worked perfectly. so, when I swap between the objects, the returned (int) number now opposite and so the positions order? – Nimrod Jun 28 '16 at 08:23
  • @Nimrod , it is wrong because it doesn't respect the contract of the method definition from `Comparable`. If you need reverse sorting, use other ways like `Collections.reverseOrder()`: https://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#reverseOrder(). – Arnaud Jun 28 '16 at 08:35
  • Sorry, but I still don't understand.. `Collections` is relevant for Lists, while I want to use an array. can you bring an example or being more specific? – Nimrod Jun 28 '16 at 13:01
  • See there for arrays : http://stackoverflow.com/questions/1694751/java-array-sort-descending, the relevant class for sorting is `Arrays`, but it behaves like `Collections` . – Arnaud Jun 28 '16 at 13:24
0

From what I understand, if the method returns a negative value (value lesser than 0), the first object comes before the second object in the sorted list. If it returns a positive value (value greater than 0), the first object comes after the second object in the sorted list. If it returns 0, both the objects are equal.

First object refers to the object referenced by the this keyword in your example, and the second object refers to the object passed in to the compareTo method.

Aditya Gupta
  • 633
  • 1
  • 4
  • 11
0

From Java API:

Compares this object with the specified object for order. Returns a negative integer, zero, or a positive integer as this object is less than, equal to, or greater than the specified object.

Link: https://docs.oracle.com/javase/7/docs/api/java/lang/Comparable.html

compareTo() method returns an integer that tells sorters the relative position between instances, such that if (a.compareTo(b) > 0), then a is considered "bigger", and should therefore appear in the sorted list afterb. Likewise if (a.compareTo(b) < 0) then a is considered "smaller".

Thus if you want ascending order, you should stick with compareTo() implementation that references this before compareObject, i.e. this.value - compareObject.value;

In short: a.compareTo(b) > 0 basically means "a is greater than b". Similarly a.compareTo(b) < 0 means "a is less than b".

Esa Lindqvist
  • 311
  • 2
  • 6
0

The compareTo method does not determine the order (ascending versus descending) of a sort operation.

The code defining the sort operation determines the order. The sort operation repeatedly calls the compareTo, at least once for each object in a collection being sorted. How the rest of the sort operation’s code tracks the results of calling your compareTo code determines if the results are ascending or descending.

For example, the Collections.sort sort operation always sorts in ascending order. The code in that library will call each of your object’s compateTo method.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154