0

I am new to java I have a class with 4 attributes , based on which i need to sort my object . I could achieve sorting upto three level ie on Author , title and price , can any one help me to extend it to publisher.

My code : Sorts object based on Author Name first , if Same Author Name it sorts on title , if same title it sorts on price .

Now i want if same price , sort on publisher . Can any one help me with this ?

Here is the code :

//Book.java

public class Book implements Comparable<Book>{

   String title;
   String author;
   double price;
   String publisher;
    //getters and setters for 4 variables
public int compareTo(Book book){

     if(book == null){
       throw new NullPointerException("Book passed is null!"); 
    }

    if(this.getAuthor().equals(book.getAuthor())){  /*Most significant field*/

     if(this.getTitle().equals(book.getTitle()))   /*Next Most significant field*/ 
            return (int)(this.getPrice()-book.getPrice());
          else
           return this.getTitle().compareTo(book.getTitle());
     }
     else
          return this.getAuthor().compareTo(book.getAuthor());

  }
}

//BookComparison.java

import java.util.Arrays;

public class BookComparision{

    public static void main(String args[]){

        Book book1 = new Book();        
        book1.setAuthor("Author A");
        book1.setTitle("Title B");
        book1.setPrice(225.00);

        Book book2 = new Book();        
        book2.setAuthor("Author A");
        book2.setTitle("Title B");
        book2.setPrice(125.00);


        Book book3 = new Book();        
        book3.setAuthor("Author B");
        book3.setTitle("Title B");
        book3.setPrice(125.00);

        Book book4 = new Book();        
        book4.setAuthor("Author B");
        book4.setTitle("Title A");
        book4.setPrice(200.00);


        Book book5 = new Book();        
        book5.setAuthor("Author C");
        book5.setTitle("Title C");
        book5.setPrice(125.00);

        Book book6 = new Book();        
        book6.setAuthor("Author C");
        book6.setTitle("Title B");
        book6.setPrice(125.00);

        Book book7 = new Book();        
        book7.setAuthor("Author C");
        book7.setTitle("Title B");
        book7.setPrice(400.00);

       /* An array containing Books*/
        Book[] bookArray = new Book[7];
        bookArray[0]=book1;
        bookArray[1]=book2;
        bookArray[2]=book3;
        bookArray[3]=book4;
        bookArray[4]=book5;
        bookArray[5]=book6;
        bookArray[6]=book7;

        System.out.println("Sorted Books:");

        Arrays.sort(bookArray);

        for(int i=0;i<=6;i++){
        System.out.print("Author:"+bookArray[i].getAuthor()+"        ");
        System.out.print("Title:"+bookArray[i].getTitle()+"        ");
        System.out.println("Price:"+bookArray[i].getPrice());

        }        
   }
 }

Thanks in Advance Manas

4
  • 1
    If you were able to implement sorting for 4 elements, where is the issue implementing just another condition? Side note: please always use braces, it makes your code more readable and less error prone. Commented Apr 12, 2014 at 6:06
  • Hi Leos , I am able to sort it on 3 attributes till now that is Author , title and price . But i want to extend the sorting to Publisher. Above code sorts only on 3 attributes not 4th one that is not based on publisher Commented Apr 12, 2014 at 6:08
  • Well, I will try to make it more readable. But where is your issue with extending the conditions? Commented Apr 12, 2014 at 6:11
  • compare authors. If not equal, you're done. Then compare titles. If not equal, you're done. Then compare prices. If not equal, you're done. Then compare publishers. Comparing uses the compareTo() method, not the equals() method. Commented Apr 12, 2014 at 6:11

6 Answers 6

1

You have the right idea already: compare each criteria until there is one that is unequal. Just do it in a more organized manner.

int dif;

dif = this.getAuthor().compareTo(book.getAuthor());
if(dif != 0)
    return dif;

dif = this.getTitle().compareTo(book.getTitle());
if(dif != 0)
    return dif;

if(this.getPrice() < book.getPrice())
    return -1;
if(this.getPrice() > book.getPrice())
    return 1;

return this.getPublisher().compareTo(book.getPublisher());

Note that I didn't use subtraction for comparing the double values. Doing (int)(double - double) will truncate a fractional value and that may not be a good idea. If you are using a newer JDK there are also static methods such as Double.compare.

Sign up to request clarification or add additional context in comments.

Comments

1

If you use String fields to compare Objects you can always fall back on the natural ordering of Strings themselves. If you have more than one criteria you can use them chronologically as follows:

public int compareTo(Book b)
{
    int compare = title.compareTo(b.getTitle());

    // the following lines only change the compare value if it is still 0
    compare = (compare != 0) ? compare : author.compareTo(b.getAuthor()); 
    compare = (compare != 0) ? compare : Double.compare(price, b.getPrice());

    return (compare != 0) ? compare : publisher.compareTo(b.getPubisher());
}

I would also not use operations like + and - with doubles because they are not accurate enough when cast to int. Imagine books with prices like 19.90 and 19.95 would sum up to int 0 which would be treated as equal (from an ordering perspective).

1 Comment

Hint: Integer.compare(i1, i2).
0

Staying consistent with the same method you've been using, if you want to add a 4th layer of comparisons for if same price --> sort by publisher, I would do something like this:

public int compareTo(Book book){

     if(book == null){
       throw new NullPointerException("Book passed is null!"); 
     }

     if(this.getAuthor().equals(book.getAuthor())){  /*Most significant field*/

       if(this.getTitle().equals(book.getTitle()))   /*Next Most significant field*/ 
           if(this.getPublisher().equals(book.getPublisher())){ //assuming that you have a getPublisher() method
               return (int)(this.getPublisher().compareTo(book.getPublisher()));
           }
           else {
               return (int)(this.getPrice()-book.getPrice());
           }
       else
           return this.getTitle().compareTo(book.getTitle());
       }
     else
        return this.getAuthor().compareTo(book.getAuthor());

    }
}

2 Comments

Thanks Wold , this solution was help full
@user3507026 No problem, glad I could help. Did the answer solve your problem?
0

You can try something like this.

public int compareTo(Book book) {

    int retval = author.compareTo(book.author);
    if(retval != 0) return retval;

    retval = title.compareTo(book.title);
    if(retval != 0) return retval;

    if(price!=book.price) return price>book.price ? 1 : -1;

    // if we reach here, all previous comparisons are equal. So just return whatever publisher compareTo returns.
    return publisher.compareTo(book.publisher);

}

Comments

0

Here is the code as discussed in comments. It is much easier to orientate in.

public int compareTo(Book book) {

    if (book == null) {
        throw new NullPointerException("Book passed is null!");
    }

    if (!this.getAuthor().equals(book.getAuthor())) {
        return this.getAuthor().compareTo(book.getAuthor());
    }

    if (! this.getTitle().equals(book.getTitle())) {
        return this.getTitle().compareTo(book.getTitle());
    }

    if (this.getPrice() != book.getPrice()) {
        return (int) (this.getPrice() - book.getPrice());
    }

    return publisher.compareTo(book.getPublisher());
}

Comments

0
  public int compareTo(Book book){

 if(book == null){
   throw new NullPointerException("Book passed is null!"); 
}

if(this.getAuthor().equals(book.getAuthor())){  /*Most significant field*/

 if(this.getTitle().equals(book.getTitle())){   /*Next Most significant field*/ 
   if(this.getPrice().equals(book.getPrice()){
      return (this.getPublisher().compareTo(book.getPublisher()); 
  }  
    else{
          return (int)(this.getPrice()-book.getPrice());
        }         
   }
      else{
       return this.getTitle().compareTo(book.getTitle());
 }}
 else{
      return this.getAuthor().compareTo(book.getAuthor());
     }
     }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.