0

I have one class "SendBundleQuery" which contains some objects like category , Type , name. category can be of two types base and Addons . Type can be of three types data, voice , sms. I have a arraylist of this class object and now i need to sort in such a was like all base offers will come first and afterwords all Addons. For all base offers order will be data , voice , SMS.

Currently i have sorted it according to category

public int compareTo(SendBundleQuery other) {
    int result= category.compareTo(other.category);
    if(result==0){
        result =other.bundleType.compareTo(bundleType);
    }
    return result;
}

But now i need to achieve the above condition. What will be the good way to do it.

Below is the example what i want to achieve.

I need to compose sms text for customer like below :

Dear Customer,

You have <0 MB> left within your <Eenmalig 100 MB Maandbundel>. ---Base offer

In addition, you have <22 Minuten> left within your <100 Minuten Bundel>. --- Base offer

In addition, you have <0 MB> left within your <Web 200 MB Maandbundel>. --Addon

In addition, you have <35 MB> left within your <Alles-in-1 op Reis Data Dagbundel>. --Addon

In addition, you have <374 MB> left within your <Blox 400 MB Maandbundel>.  --Addon

In addition, you have <20 Minuten> left within your <Alles-in-1 Op Reis 20 Minuten gesprekken ontvangen>.  --Addon

In addition, you have <20 Minuten> left within your <Alles-in-1 Op Reis 20 Minuten Bellen>.  --Addon

In addition, you have <20 SMS> left within your <Alles-in-1 Op Reis 20 SMS Dagbundel>.  --Addon

These credits are updated until <12-12-2014> at <14.53>.

Maintain your BloX and extra’s in My Vodafone.

Below is the current result but the order is like data , sms and then voice but i need data , voice and then sms:

        Dear Customer,

        You have 0.0 MB Data left within your Web 500 MB Maandbundel.

        In addition, you have 106 minutes left within your 150 Minuten Bundel.

        In addition, you have 35.0 MB Data left within your Alles-in-1 op Reis Data Dagbundel.

        In addition, you have 20 messages left within your Alles-in-1 Op Reis 20 SMS Dagbundel.

        In addition, you have 20 minutes left within your Alles-in-1 Op Reis 20 Minuten gesprekken ontvangen.

        In addition, you have 20 minutes left within your Alles-in-1 Op Reis 20 Minuten Bellen.

        These credits are updated until 15-12-2014 at 03:57.

        Maintain your BloX and extras in My Vodafone.
Tarun Bharti
  • 185
  • 3
  • 17
  • 1
    Could you provide an example? Your description is, to put it charitably, unclear. – Scott Hunter Jan 06 '15 at 14:23
  • Your compareTo method should have how it is sorted by you can override the compareTo method and sort by item1 first if they are equal then by item2 if they are equal then by item3 etc...? – brso05 Jan 06 '15 at 14:27
  • It sounds like you just need to learn how to use different comparators in different circumstances. There are some examples here: http://stackoverflow.com/questions/2839137/how-to-use-comparator-in-java-to-sort – Steve Jan 06 '15 at 16:42

3 Answers3

2

In order to sort by multiple criteria, write compareTo in following way:

public int compareTo(SendBundleQuery other) {
    int result = category1.compareTo(other.category1);
    if( result == 0 ) {
         result = category2.compareTo(other.category2);
    }
    return result;
}
lopisan
  • 7,720
  • 3
  • 37
  • 45
  • And if you can use Google Guava, you can use [`ComparisonChain`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ComparisonChain.html) to make this code simpler. – Florent Bayle Jan 06 '15 at 14:39
  • Your solution is not giving what i desired. it is sorting in data , sms the voice but i need data, voice then sms – Tarun Bharti Jan 06 '15 at 15:26
  • How data, sms and voice are recognized? Enums? Integers? It is a `category` property? So it should be the first category (`category1`) in my example. Make sure that `category.compareTo()` compare your categories correctly. Then use `category2` to sort by other conditions (date, MB left, ...) – lopisan Jan 06 '15 at 16:06
  • I am getting a soap request with name and value pair . So i added them in a MAP then making a arraylist – Tarun Bharti Jan 06 '15 at 16:18
  • it looks like the category is ordered alphabetically (data, sms, voice), but you want it in other way (data, voice, sms) so you have to write custom comparator (compare category explicitelly) - e.g. replacing category string by .replace("sms", "z") – lopisan Jan 06 '15 at 16:40
2

If you have multiple conditions to check, then check them in order of importance. Whenever the result of a comparison is 0 (ie; in thát condition they are equal) continue checking the next.

An empty example because I do not have enough information to give you exact code based on your post:

public int compareTo(SomeObject other) {
    int comparison1 = someProperty.compareTo(other.someProperty);
    if( comparison1 != 0 ) {
      return comparison1; // the highest priority ordening is leading
    }
    int comparison2 = someLessImportantProperty.compareTo(other.someLessImportantProperty);
    if( comparison2 != 0 ) {
      return comparison2; // the second highest priority ordening is leading
    }

    // if neither of the more important ones matter; sort by the least important one
    return someUnImportantProperty.compareTo(other.someUnImportantProperty);

}
Erik
  • 3,598
  • 14
  • 29
  • And if you can use Google Guava, you can use [`ComparisonChain`](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/collect/ComparisonChain.html) to make this code simpler. – Florent Bayle Jan 06 '15 at 14:36
  • Your solution is not giving what i desired. it is sorting in data , sms the voice but i need data, voice then sms – Tarun Bharti Jan 06 '15 at 15:26
  • Edit the question with what you have now. There's probably something wrong in your own order function. – Erik Jan 06 '15 at 15:41
  • I edited the question now , please suggest some logic for it. – Tarun Bharti Jan 06 '15 at 16:25
1

Since Java 8 Method references and lambda's added an extra set of elegant ways for common sorting requirements. One of those is what you required: first sort based on property x and if that is not available sort based on property y.

humans.sort(Comparator.comparing(Human::getName).thenComparing(Human::getAge));

(full example available here).

This will sort a list of Human objects based on the two getter methods.

For you the Human is SendBundleQuery, and the getters are what you require your sorting to be.

Thirler
  • 20,239
  • 14
  • 63
  • 92